PDA

View Full Version : QAudioOutput & QAudioFormat::Float



Biberbaer
23rd April 2012, 23:28
Hey all,
currently I have a problem in my audio-player project with the float sample type. Other sample types like QAudioFormat::SignedInt and QAudioFormat::UnSignedInt work as expected. However, if I try to play audio streams with the sample type QAudioFormat::Float (e.g. pcm_f32le), I just hear noise. Here's what I did for now:

MBuffer.cpp:

MBuffer::MBuffer(AVFormatContext *formatContext, AVCodecContext *codecCtx, int audio_stream, QObject *parent):
QBuffer(parent),formatContext(formatContext), codecContext(codecCtx), audioStream(audio_stream)
{
med_buffer = (uint8_t*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);

buffer_offset = 0;
pkt_size_remaining = 0;
}
qint64 MBuffer::readData(char *data, qint64 maxlen)
{
qint64 written = 0;
AVPacket packet;

av_init_packet(&packet);

while( pkt_size_remaining == 0 )
{
int error;
qDebug() << "pkt_size_remaining == 0 -> read new packet";
if( (error = av_read_frame(formatContext, &packet)) != 0 )
{
qWarning() << "couldnt read packet AVERROR= " << error;
return 0;
}
if( packet.stream_index == audioStream )
{
pkt_data_pointer = packet.data;
pkt_size_remaining = packet.size;
}
}

while(pkt_size_remaining > 0)
{
int len, data_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;


packet.data = pkt_data_pointer;
packet.size = pkt_size_remaining;

//decode
len = avcodec_decode_audio3(codecContext, (int16_t*)med_buffer, &data_size, &packet );
if( len <= 0 )
qWarning() << "no data read from packet";
else
{
pkt_size_remaining -= len;
pkt_data_pointer += len;
}
if( data_size > 0 )
{
memcpy((void*)data, (const void*)med_buffer, data_size );
written = data_size;
}
qDebug() << "data_size= " << data_size << "\twritten= " << written;
qDebug() << "maxlen= " << maxlen;
}
return written;
}

DecodeThread.cpp:

void DecodeThread::openFile()
{
av_register_all();

audioStream = -1;
AVCodec *codec;

if( av_open_input_file(&formatContext, WMV, NULL,0,NULL) != 0 )
qWarning() << "couldnt open input file";

if( av_find_stream_info(formatContext) < 0 )
qWarning() << "couldnt obtain stream info";

av_dump_format(formatContext, 0, WMV,0);

for( unsigned int i=0; i < formatContext->nb_streams; i++ )
{
if( formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO )
{
audioStream = i;
break;
}
}
if( audioStream == -1 )
{
qWarning() << "could not find audio stream";
return;
}

codecContext = formatContext->streams[audioStream]->codec;

codec = avcodec_find_decoder(codecContext->codec_id);
if(!codec)
qWarning() << "no codec found";

if( avcodec_open(codecContext,codec) < 0)
qWarning() << "could not open codec";
}

void DecodeThread::startAudio()
{
openFile();

MBuffer *buffer = new MBuffer(formatContext,codecContext, audioStream);
if( !buffer->open(QBuffer::ReadOnly) )
qDebug() << "couldnt open buffer";

// QAudioFormat format;
// format.setFrequency(codecContext->sample_rate);
// format.setChannels(2);
// format.setSampleSize(16);
// format.setCodec("audio/pcm");
// format.setByteOrder(QAudioFormat::LittleEndian);
// format.setSampleType(QAudioFormat::SignedInt);

QAudioFormat format;
format.setFrequency(codecContext->sample_rate);
format.setChannels(2);
format.setSampleSize(32);
format.setSampleType(QAudioFormat::Float);
format.setByteOrder(QAudioFormat::LittleEndian);
format.setCodec("audio/pcm");

if( !format.isValid() ) {
qWarning() << "format is invalid!!";
}

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());

// qDebug() << "Codecs= " << info.supportedCodecs();
// qDebug() << "SampleTypes= " << info.supportedSampleTypes();
// qDebug() << "Channels= " << info.supportedChannelCounts();
// qDebug() << "ByteOrders= " << info.supportedByteOrders();
// qDebug() << "Frequencies= " << info.supportedFrequencies();

if (!info.isFormatSupported(format)) {
qWarning()<<"raw audio format not supported by backend, cannot play audio.";
format = info.nearestFormat(format);
}

if( !format.isValid() ) {
qWarning() << "still not supported!";
return;
}

QAudioOutput *output = new QAudioOutput(format);
output->start(buffer);

}

Thanks in advance,
Biberbaer