Playing ulaw file with QAudioOutput - qt

I'm trying to set up a simple working example to play a .raw file and the audio seems to be distorted. When the .raw file plays, I can still make out everything, its just fairly distorted, like listening to a radio station going out of range.
QString mResourcePath ="test.raw";
QFile audio_file(mResourcePath);
if(audio_file.open(QIODevice::ReadOnly)) {
audio_file.seek(4); // skip wav header
QByteArray audio_data = audio_file.readAll();
audio_file.close();
QBuffer audio_buffer(&audio_data);
audio_buffer.open(QIODevice::ReadOnly);
qDebug() << audio_buffer.size();
QAudioFormat format;
format.setSampleSize(8);
format.setSampleRate(8000);
format.setChannelCount(1);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::BigEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
qWarning()<<"raw audio format not supported by backend, cannot play audio.";
return;
}
qDebug() << info.deviceName();
QAudioOutput output(info, format);
output.start(&audio_buffer);
// ...then wait for the sound to finish
QEventLoop loop;
QObject::connect(&output, SIGNAL(stateChanged(QAudio::State)), &loop, SLOT(quit()));
do {
loop.exec();
} while(output.state() == QAudio::ActiveState);
}

The title of your question indicates that you wish to play u-law audio, which is logarithmic PCM. Yet, the line
format.setCodec("audio/pcm");
initializes playback for linear PCM. 2 possible solutions:
Initialize playback with the appropriate log PCM codec. The docs report that QAudioDeviceInfo::supportedCodecs() will return a list of supported codecs.
Convert the log PCM samples to linear PCM in real time. It's pretty low impact and can be performed using a lookup table.

Related

Play video using QMediaplayer from buffer and append buffer while the video playing

I tried to play video from a buffer and append the buffer while playing so the two or more videos play after each other without any delay as they are one video, I tried to use the QMediaPlaylist and append the list during run time, it worked but there is a Noticeable delay between the videos I use this code in the play button
void MainWindow::on_pushButton_2_clicked()
{
player = new QMediaPlayer(this);
QFile file("D:/video/first.mp4");
file.open(QIODevice::ReadOnly);
arr = new QByteArray();
arr->append(file.readAll());
file.close();
buffer = new QBuffer(arr);
buffer->open(QIODevice::ReadWrite);
player->setVideoOutput(ui->widget);
player->setMedia(QMediaContent(), buffer);
player->play();
}
and a button to append the second video during the runtime which is here I make many different trys
void MainWindow::on_pushButton_3_clicked()
{
QFile file("D:/video/second.mp4");
file.open(QIODevice::ReadOnly);
QByteArray temp = file.readAll();
//arr->append(temp, temp.size()); //first to append the QByteArray did not work
buffer->write(temp.data(), temp.size()); //second write to the buffer but not work
file.close();
qDebug() << "Appeneded";
}
first one which is append the array but it did not work, same as when i set the buffer to ReadWrite flage and its the same result, the result is that only the first video is played and it stop,
so can you help me to make this work? what i did wrong in my code let the second video not run smoothly after first video and this is the result i want.

I want to creat a small tool to record audio,during the recording, there was a lot of extra noise during the recording

Thank you to see:
Development environment: QT、windows
Problem: I want to creat a small tool to record audio,during the recording, there was a lot of extra noise during the recording. why? can you help me?
function: init()
{
outputFile.setFileName("test.raw");
outputFile.open( QIODevice::WriteOnly | QIODevice::Truncate );
QAudioFormat format;
format.setSampleRate(8000);
format.setChannelCount(1);
format.setSampleSize(8);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
if (!info.isFormatSupported(format))
{
qWarning()<<"default format not supported try to use nearest";
format = info.nearestFormat(format);
}
audio = new QAudioInput(info, format, this);
QTimer::singleShot(10000, this, SLOT(stopRecording()));
audio->start(&outputFile);
qDebug() <<"record begin!";
}
function: stopRecording()
{
audio->stop();
outputFile.close();
delete audio;
qDebug() <<"record end!";
}
record audio,You have to make sure that QT setting is the same as your System Settings.
firstly:What you need to record? microphone or a system sound.
secondly: Set the format of it
like:
QAudioFormat format;
format.setSampleRate(8000);
format.setChannelCount(1);
format.setSampleSize(16);

set image raw data buffer to QMediaPlayer

I want to get a screen shot of the widget application and then set its raw data buffer to QMeidaPlayer with setMedia(). What I have done so far is to receive the image, SAVE it, and then read from it. However, I would like to ask you how to read raw data directly without saving it into media player:
QPixmap originalPixmap = QPixmap::grabWidget(this);
QImage *image = new QImage(originalPixmap.toImage());
QByteArray ba;
QBuffer buffer(&ba);
buffer.setBuffer(&ba);
buffer.open(QIODevice::WriteOnly);
image->save(&buffer); // writes image into ba in PNG format
image->save(image Path);
mediaPlayer.setMedia(QUrl::fromLocalFile(image path)); //I want this to read from raw data
mediaPlayer.play();
I want this to take the minimum CPU usage. However, saving and reading from file consumes lots of CPU,47%.
Cheers,
Update: I tested the program with this code snippet as well. But it does not draw the buffer contents on video widget.
QBuffer *buffer = new QBuffer(image_ba);
QMediaContent media;
mediaPlayer.setMedia(media, buffer);
mediaPlayer.play();
Any ideas how I can resolve this to input image raw data to video widget?
here's how you can do it:
QPixmap originalPixmap = QPixmap::grabWidget(this);
QBuffer *buffer = new QBuffer(); // make sure that your buffer has the same life span as your media player, or otherwise the media player would try to read data from non-existing buffer. (the setMedia() and play() methods are non-blocking)
buffer.open(QIODevice::ReadWrite);
originalPixmap.save(buffer, "PNG"); // can be any other format, not just PNG
mediaPlayer.setMedia(QUrl(), buffer);
mediaPlayer.play();

Does QBuffer write data in system dependent byte order?

The documentation says that QDataStream writes data in system independent way, but it says nothing about QBuffer. I develop a program that saves data in a file like this:
QByteArray a;
QBuffer b(&a);
b.open(QIODevide::WriteOnly);
quint32 x = 1;
b.write((char*)&x, sizeof(x));
b.close();
QFile f(...);
f.open(QIODevide::WriteOnly);
f.write(a.constData(), a.size());
f.close();
, and i want this file can be read in any other OS (win, linux, Mac OS). Will this code work or i must use QDataStream instead?
The QBuffer documentation says :
The QBuffer class provides a QIODevice interface for a QByteArray.
ie it is only a QByteArray underneath. On the other hand a QByteArray is portable because as long as you see the data as an array of byte and write one byte at a time you are fine. Your code will work:
When you say
I want this file to be read in any other OS
Is your file used by your program only or will it be used by other applications in the system? QDataStream provides nicer functions for I\O and you may be still able to take advantage of it.
It will be platform specific. x representation in memory depend on the endianess.It doesn't occur in the QBuffer, but when you do :
b.write((char*)&x, sizeof(x));
If you are on machines of different endianess, you will obtain different values for the resulting array by doing
char* data = &x;
qDebug()<< data[0];
qDebug()<< data[1];
qDebug()<< data[2];
qDebug()<< data[3];
Take a look at the source code of QDataStream operator
QDataStream &QDataStream::operator<<(qint32 i){
CHECK_STREAM_WRITE_PRECOND(*this)
if (!noswap) {
i = qbswap(i);
}
if (dev->write((char *)&i, sizeof(qint32)) != sizeof(qint32))
q_status = WriteFailed;
return *this;
}

Does QAudioOutput::start() need to be called from main thread?

I am playing audio in my code like this:
// decode routine
QAudioFormat format;
format.setFrequency(aCodecCtx->sample_rate);
format.setChannels(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
cout<<"raw audio format not supported by backend, cannot play audio." <<endl;
format = info.nearestFormat(format);
}
QAudioOutput * audio = new QAudioOutput(format);
connect(audio,SIGNAL(stateChanged(QAudio::State)),SLOT(stateChanged(QAudio::State)));
if( !buffer->open(QBuffer::ReadWrite) )
cout << "Couldnt open Buffer" << endl;
cout << "buffer.size()=" << buffer->size() <<endl;
audio->start(buffer);
I was running this code in a worker thread because the decoder routine is heavy. But no sound was playing. I shifted this code to the main thread and everything works fine.
Why is this so? The QAudioOutput doc does not say anything about which thread it needs to run on
I forgot to start an event loop in the worker thread. Otherwise the thread exits and that's why the audio does not play

Resources