QAudioOutput in Qt5 is not producing any sound - qt

I’m working under kubuntu 12.10 and developping an application into which i need to generate some sound into a QIODevice, then play it with QAudioOutput.
I’ve read all the litterature around speaking of how to properly do that, and I think to have done so.
So far I’ve done :
QVector <double> * soundData = SoundGenerator::getSound();
soundBuffer->open(QIODevice::ReadWrite);
QDataStream writeStream(soundBuffer);
foreach(double d, *soundData) {
char value = d * (2 << 7);
// qDebug() << "Value : " << (short int)value;
writeStream << value;
}
QAudioFormat format;
// Set up the format, eg.
format.setSampleRate(SoundGenerator::getAudioSampleRate());
format.setChannelCount(1);
format.setSampleSize(8);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::SignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
audio = new QAudioOutput(format, this);
if (audio->error() != QAudio::NoError) {
qDebug() << "Problem playing sound";
}
connect(audio, SIGNAL(stateChanged(QAudio::State)), this, SLOT(aboutToFinish(QAudio::State)));
I have also a call to
audio->start(soundBuffer)
—
from another slot
I do not have any error in the initialization of the QAudioOutput
And I have NO SOUND AT ALL (all other applications have sound, and I’m porting a Qt4 app to Qt5, in Qt4 everything is ok with Phonon)
The aboutToFinish slot is called at the beggining with ActiveState as state, and NoError when calling QAudioOutput::error, but it’s not called anymore, even if waiting far more than the expected generated sound duration.
The sound generation process is not to be put in question, it has been tested by writing wav files, and it works.
Moreover, I have built the multimedia example from Qt’s sources, when it comes to pure audio there is no output (for example in the sprectrum example), on another hand, video plays with the sound perfectly.
Is there any known issue concerning that ? Is that a bug ? Am I doing something wrong ?
Thanks in advance ;)

This does not work because you have set 8 bit sample size and signed integer format.
SOLUTION: You have to set the sample type to unsigned for 8-bit resolution:
format.setSampleType(QAudioFormat::UnsignedInt);
This is not a Qt bug. Why? The answer is that in the WAV spec', 8-bit samples are always unsigned, whereas 16-bit samples are always signed. Any other combination does not work.
So for 16-bit samples you would have to put:
format.setSampleType(QAudioFormat:SignedInt);
(IMHO the fact that Qt does not take care of handling these cases by forcing the correct format is a flaw but not a lack in functionnality).
You can learn more about this in the notes section of this page: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
And also the solution to this very similar question (same problem but with 16-bit): Qt QAudioOutput push mode

Try to add:
QEventLoop loop;
loop.exec();

Related

How to prevent QAudioInput from automatically boosting the master volume to 100%?

I'm trying to use Qt5 Multimedia to record audio with QAudioInput. I noticed, however, that when my QAudioInput starts, it raises the master volume of my sound device to 100%.
How can I prevent QAudioInput from changing the master volume?
My current development platform is Linux with PulseAudio (with flat audio disabled).
This is how I'm using QAudioInput:
QAudioDeviceInfo device_info = QAudioDeviceInfo::defaultInputDevice();
QAudioFormat format;
format.setSampleRate(44100);
format.setChannelCount(1);
format.setSampleSize(16) ;
format.setCodec("audio/pcm");
format.setSampleType(QAudioFormat::SignedInt);
format.setByteOrder(QAudioFormat::LittleEndian);
std::cout << device_info.deviceName().toUtf8().constData() << std::endl;
QAudioInput *default_device = new QAudioInput(device_info, format);
QIODevice *default_io_device = default_device->start();
There is a QAudioInput.setVolume() method if you have not seen. Having said that, I tried using QAudioRecorder.setVolume() and Qt is telling me - "Setting volume while recording is not supported".

Is there a way in Qt to force QMediaPlayer to buffer a file without playing it?

When you load a file into a QMediaPlayer instance, it does not automatically buffer the file. The MediaStatus remains NoMedia until you play the file using play(), only after which it will end up as BufferedMedia. I can't find any way in the documentation to force the player to buffer the file without playing it - is there any way to do this?
Right now I'm planning on muting it, playing the file, then stopping it again and unmuting it, but it makes me feel dirty. Surely there is a better way to do this?
This is necessary, by the way, because I can't retrieve the duration until the file has been buffered, and I need the duration to select a position in the track to start playing from.
Thanks
The MediaStatus remains NoMedia until you play the file using play()
Not in Qt 5, and its not the reason you can't know 'duration' and set 'position'.
When you set the media with setMedia it does not wait for the media to finish loading (and does not check for errors). a signal mediaStatusChanged() is emitted when media is loaded, so listen to that signal and error() signal to be notified when the media loading is finished.
connect(player, &QMediaPlayer::mediaStatusChanged, this, [=]() {
qDebug() << "Media Status:" << player->mediaStatus();
});
I need the duration to select a position in the track to start playing
from.
Once the media file is loaded and before play, you can check the duration and you can set the player to your desired position, but this is best to do once the duration changes from 0 to the media duration after loading, so connect to signal durationChanged():
connect(player, &QMediaPlayer::durationChanged, this, [&](qint64 duration) {
qDebug() << "Media duration = " << duration;
player->setPosition(duration/2);
qDebug() << "Set position:" << player->position();
});
I can't find any way in the documentation to force the player to
buffer the file without playing it - is there any way to do this?
Yes, create a buffer from file then set media content to your buffer (but this is not required to do the above, it just provides a faster way to seek in media):
QString fileName=QFileDialog::getOpenFileName(this,"Select:","","( *.mp3)");
QFile mediafile(fileName);
mediafile.open(QIODevice::ReadOnly);
QByteArray *ba = new QByteArray();
ba->append(mediafile.readAll());
QBuffer *buffer = new QBuffer(ba);
buffer->open(QIODevice::ReadOnly);
buffer->reset(); //seek 0
player->setMedia(QMediaContent(), buffer);

converting a windows shell IStream to std::ifstream/std::get_line

We have a lot of code written that makes use of the standard template library. I would like to integrate some of our apps into the windows shell, which should provide a better experience for our users.
One piece of integration involves a Shell Preview provider, the code is very straight forward, however, I’m stuck on the best way to implement something.
The shell is giving me, via my preview handler, an IStream object and I need to convert/adapt it to an std::ifstream object, primarily so that std::getline can get called further down the callstack.
I was wondering if there was a “standard” way of doing the adapting or do I need to role up my sleeves and code?
TIA.
Faffed around with this for a while:
std::stringstream buff;
BYTE ib[2048];
ULONG totread=0, read=0, sbuff = 2048;
HRESULT hr;
do {
hr = WinInputStream->Read(ib, sbuff, &read);
buff.write(ib, read);
totread+=read;
} while((sbuff == read) && SUCCEEDED(hr));
if(totread == 0) return false;
ifstream i;
TCHAR* ncbuff = const_cast<TCHAR*>(buff.str().c_str());
i.rdbuf()->pubsetbuf(ncbuff, buff.str().length());
But didn't like having to read it all into memory, for it to be processed again.
So I implemented my preview handler using IInitializeWithFile instead.

How to set path to memory card of the mobile?

I am using latest qt version 4.7,where i developed an application on Audio Recording.
I need to set the path to memory card(ie,mass memory),I have seen links based on carbide link->How to run C++ applications in symbian
But could not find any solution for this latest version.
Can anyone help me out in finding this!!
This is what i tried.
I used two methods but i am clueless….
But the audio file gets stored in simulator ,,but not in desired memory card location!!!
AudioBuffer::AudioBuffer()
{
audioSource = new QAudioCaptureSource();
capture = new QMediaRecorder(audioSource);
QAudioEncoderSettings audioSettings;
audioSettings.setCodec("audio/vorbis");
audioSettings.setQuality(QtMultimediaKit::HighQuality);
capture->setEncodingSettings(audioSettings);
capture->setOutputLocation(QUrl::fromLocalFile("test.wav"));
FileName path = PathInfo::MemoryCardRootPath();
path.Append( PathInfo::SoundsPath() );
// QFile file;
// QDir::setCurrent("/tmp");
// file.setFileName("test.wav");
// QDir::setCurrent("/home");
// file.open(QIODevice::ReadOnly);
}
I am using Symbian platform(Qt-Quick)
Regards,
Harish.
I don't develop applications for symbian platforms but IMHO you have to convert TDesC path to a QString (see Converting a Descriptor to a QString for details).
Internal memory is hardcoded to "E:/" and SD card is hardcoded to "F:/" on symbian.
Do a :
QDir d;
d.setPath("f:/");
if (d.exists()) {
[...]
}
to check the availability of the external storage

Warning: XXX may not respond to YYY

Hey, I am making some stuff in Objective-C++... And I must say that I am a total newbie when it comes to the Objective-C part... I don't really want to learn it, I kinda just need it for accessing a few Mac APIs (ObjC is such a dumb language).
So - compiling with g++ -x objective-c++ - and I somehow keep getting this warning:
XXX may not respond to YYY
First it was with a NSScreen, now it is with a NSWindow:
NSWindow may not respond to +initWithContentRect:styleMask:backing:defer:
I saw somewhere that I should cast it to id, but didn't work, throwing absolutely cryptic errors...
So - WHAT does this warning actually mean and HOW am I supposed to make it stop?
EDIT: Okay, apparently I need to ALLOCATE an instance first, then I can call its init function... Anyways, now the GCC is reporting:
confused by earlier errors, bailing out
And NOTHING else. This is the ONLY error that it reports. I figured that there is some error in my code that doesn't get reported... So I will post the whole file where the problem is here:
ONXeWindow::ONXeWindow(int px, int py, int sw, int sh, bool resizable){
NSRect wr = NSMakeRect(px, py, sw, sh);
int wf = 1; // titled
wf += 2; // closable
wf += 4; // miniaturizable
wf += (resizable ? 8 : 0); // resizable
wf += (false ? 128 : 0); // metal bg
useWindow = [[NSWindow alloc] initWithContentRect:wr styleMask:wf backing:2 defer:YES];
}
Also, YES, framework AppKit was imported (in the header file) - I am not going to confuse you with my weird file scheme here.
The message isn't really cryptic, you just don't know the language (and don't care to, by your own admission).
Since Objective-C methods are dispatched dynamically at run-time, you can call a method that the compiler doesn't have any knowledge of, however, the compiler is warning you that you're doing so. The + in the beginning of the method name means that you're calling a class method (a - would indicate that you're calling a method on an instance). Since NSWindow has no class method named initWithContentRect:styleMask:backing:defer:, the compiler is giving you a warning, and in this case, it's a pretty good one.
You probably wrote something like:
NSWindow* myWindow = [NSWindow initWithContentRect:rect styleMask:0 backing:0 defer:NO];
when you meant to write something like:
NSWindow* myWindow = [[NSWindow alloc] initWithContentRect:rect styleMask:0 backing:0 defer:NO];
The first one sends the message directly to the class, but this is an instance method. You need to allocate an instance of NSWindow first, then send the init message. Also, clang tends to give much better warning and error messages than gcc. Clang 2.0 also handles C++ and ObjC++ pretty well, so it might be worth it to switch to clang.
Checkout this example, looks like you are not allocating your objects.

Resources