Hello,
I'm using sf::SoundRecorder / sf::SoundStream to make a VOIP client. The recording and the networking (using Qt for the later) are working just fine (except that the SoundRecorder crash on exit, go figure), but I'm running into a weird behavior when I'm subclassing sf::SoundStream.
Beforehand, my code:
Sound.h
#ifndef DEF_SOUND
#define DEF_SOUND
/* Some includes */
class Sound : public QObject, public sf::SoundStream
{
Q_OBJECT
public:
Sound(size_t sampleRate);
protected:
virtual bool OnGetData(Chunk& Data);
public slots:
void queue(const IntVector & samples);
private:
sf::Mutex m_bmux;
QQueue<IntVector > m_buff;
size_t m_sampleRate;
};
#endif
Sound.cpp
#include "Sound.h"
#include <QDebug>
#define D() qDebug() << __FILE__ << ";" << __LINE__
Sound::Sound(size_t sampleRate):sf::SoundStream()
{
m_sampleRate=sampleRate;
Initialize(1, m_sampleRate);
Play();
}
bool Sound::OnGetData(Chunk& Data)
{
m_bmux.Lock();
if(m_buff.size()<1)
{
m_bmux.Unlock();
return true;
}
IntVector bu = m_buff.dequeue();
m_bmux.Unlock();
size_t bfs=bu.size();
sf::Int16* bf=new sf::Int16[bfs]; //Possible memory leak? SFML documentation is unclear about that...
for(size_t i=0;i<bfs;++i)
bf[i]=bu[i];
Data.Samples = bf;
Data.NbSamples = bfs;
D() << "B";
return true;
}
void Sound::queue(const IntVector & samples)
{
m_bmux.Lock();
if(m_buff.size() < 150)
m_buff.enqueue(samples);
else
D() << "Buffer full!";
m_bmux.Unlock();
Play();
D() << "A";
}
IntVector is a QVector<sf::Int16> typedef.
All the Qt containers behave like STL's here. A queue's a queue, and a "vector" is a wrapper over a C-array.
I call queue() every once in a while (each time I receive a frame). For debug purpose it's at the moment directly connected to a sf::SoundRecorder.
The minor part of the problem:
in OnGetData(), do I loose the ownership of the data array I put into the chunk? Both the documentation and the tutorial are very vague about it.
The MAJOR part of the problem:
I expected the console output to be ABABAB..., give or take.
What I get, however, is "ABBBAAAAAAAAAA...". OnGetData() just stop being called, yet the GetState() function still return Playing.
I tried delaying the Play() call, calling it only when there are at least 3 frames in the buffer. This time I got "AAABBBAABBAABBAABBAAAAAAAAAAAAAAAAAA...", so it's kind of better, but it's still broken.
I tried calling Initialize(), Stop(), etc. pretty much everywhere in the code, obviously it just doesn't work this way.
I'm compiling with Mingw32, on a 64bits Windows 7. I used to work with OpenAL directly, but it was a pain to debug and to maintain, this is why I switched to SFML 1.6 for the VOIP.
Anyone got a suggestion on what's wrong with what I've done here?
Thanks,
Gig
PS: I apologize for my English, it is not my mothertongue.