aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/General/converter/converter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/General/converter/converter.cpp')
-rw-r--r--src/plugins/General/converter/converter.cpp93
1 files changed, 40 insertions, 53 deletions
diff --git a/src/plugins/General/converter/converter.cpp b/src/plugins/General/converter/converter.cpp
index 9a370af09..655eb780b 100644
--- a/src/plugins/General/converter/converter.cpp
+++ b/src/plugins/General/converter/converter.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2011-2015 by Ilya Kotov *
+ * Copyright (C) 2011-2016 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -24,6 +24,8 @@
#include <qmmp/inputsourcefactory.h>
#include <qmmp/decoderfactory.h>
#include <qmmp/metadatamanager.h>
+#include <qmmp/audioconverter.h>
+#include <qmmp/buffer.h>
#include <qmmpui/metadataformatter.h>
#include <QtEndian>
#include <taglib/fileref.h>
@@ -33,28 +35,6 @@
#define QStringToTString_qt4(s) TagLib::String(s.toUtf8().constData(), TagLib::String::UTF8)
-//static functions
-static inline void s8_to_s16_2(qint8 *in, qint16 *out, qint64 samples)
-{
- for(qint64 i = 0; i < samples; ++i)
- out[i] = in[i] << 8;
- return;
-}
-
-static inline void s24_to_s16_2(qint32 *in, qint16 *out, qint64 samples)
-{
- for(qint64 i = 0; i < samples; ++i)
- out[i] = in[i] >> 8;
- return;
-}
-
-static inline void s32_to_s16_2(qint32 *in, qint16 *out, qint64 samples)
-{
- for(qint64 i = 0; i < samples; ++i)
- out[i] = in[i] >> 16;
- return;
-}
-
Converter::Converter(QObject *parent) : QThread(parent)
{}
@@ -305,55 +285,62 @@ void Converter::run()
bool Converter::convert(Decoder *decoder, FILE *file, bool use16bit)
{
- const int buf_size = 8192;
AudioParameters ap = decoder->audioParameters();
- Qmmp::AudioFormat format = ap.format();
- unsigned char output_buf[(use16bit && format == Qmmp::PCM_S8) ? buf_size : buf_size * 2];
- qint64 output_at = 0;
- qint64 total = 0;
- quint64 len = 0;
- qint64 totalSize = decoder->totalTime() * ap.sampleRate() * ap.channels() * ap.sampleSize() / 1000;
-
+ AudioConverter inConverter, outConverter;
+ qint64 len, total = 0;
+ Qmmp::AudioFormat outFormat = Qmmp::PCM_S16LE;
int percent = 0;
int prev_percent = 0;
+ int samples = 0, output_at = 0;
+
+ qint64 totalSize = decoder->totalTime() * ap.sampleRate() * ap.channels() * ap.sampleSize() / 1000;
+
+ inConverter.configure(ap.format());
+
+ if(use16bit)
+ outFormat = Qmmp::PCM_S16LE;
+ else if(ap.sampleSize() == 1)
+ outFormat = Qmmp::PCM_S8;
+ else if(ap.sampleSize() == 2)
+ outFormat = Qmmp::PCM_S16LE;
+ else if(ap.sampleSize() == 4)
+ outFormat = Qmmp::PCM_S32LE;
+
+ outConverter.configure(outFormat);
+
+ int outSampleSize = AudioParameters::sampleSize(outFormat);
+
+ unsigned char input_buffer[QMMP_BLOCK_FRAMES * ap.sampleSize() * ap.channels() * 4];
+ float converter_buffer[QMMP_BLOCK_FRAMES * ap.channels() * 4];
+ unsigned char output_buffer[QMMP_BLOCK_FRAMES * outSampleSize * ap.channels() * 4];
+
+ emit progress(0);
+
forever
{
// decode
- len = decoder->read((output_buf + output_at), buf_size - output_at);
+ len = decoder->read(input_buffer, sizeof(input_buffer));
if (len > 0)
{
- output_at += len;
total += len;
- if(use16bit) //TODO dithering support
- {
- if(format == Qmmp::PCM_S8)
- {
- s8_to_s16_2((qint8 *)output_buf, (qint16 *)output_buf, output_at);
- output_at <<= 1;
- }
- else if(format == Qmmp::PCM_S24LE)
- {
- s24_to_s16_2((qint32 *)output_buf, (qint16 *)output_buf, output_at >> 2);
- output_at >>= 1;
- }
- else if(format == Qmmp::PCM_S32LE)
- {
- s32_to_s16_2((qint32 *)output_buf, (qint16 *)output_buf, output_at >> 2);
- output_at >>= 1;
- }
- }
+ samples = len / ap.sampleSize();
+
+ inConverter.toFloat(input_buffer, converter_buffer, samples);
+ outConverter.fromFloat(converter_buffer, output_buffer, samples);
+ output_at = samples * outSampleSize;
+
while(output_at > 0)
{
- len = fwrite(output_buf, 1, output_at, file);
+ len = fwrite(output_buffer, 1, output_at, file);
if(len == 0)
{
qWarning("Converter: error");
return false;
}
output_at -= len;
- memmove(output_buf, output_buf + len, output_at);
+ memmove(output_buffer, output_buffer + len, output_at);
}
percent = 100 * total / totalSize;
if(percent != prev_percent)