0
0

Greetings everyone!

I have a problem regarding a custom stream which a want to feed with stored sound data. This is what I am trying to do:

  • Record some sound, store the raw data using lock/unlock into a std::queue.
  • Playback the sound in a stream by feeding the stream with data from the queue.

During playback, the sound has a alot of disturbance and only half the recorded sound is heard. I think the recording part is correct, my guess is I am doing something wrong in stream callback or something.

I have tried to compress the code to keep it as short as possible. Anyway, here it is:

[code:3f4k3bbj]

include <stdio.h>

include <conio.h>

include <windows.h>

include <queue>

include "fmod.h"

include "fmod_errors.h"

define OUTPUTRATE 44100

define RECORDRATE 44100

define RECORDLEN (RECORDRATE * 5)

typedef std::queue<signed short> SoundQueue;

signed char F_CALLBACKAPI streamcallback(FSOUND_STREAM stream, void *buff, int len, void *param)
{
unsigned int count = len / sizeof(signed short);
signed short
soundBuffer = (signed short) buff;
SoundQueue
pQueue = (SoundQueue*) param;

// JUST SILENCE IF NO DATA IS PRESENT
if(pQueue &amp;&amp; pQueue-&gt;empty())
{
    memset(soundBuffer, 0, len);
    return true;
}

for(; count &gt; 0 &amp;&amp; !pQueue-&gt;empty(); count--)
{
    *soundBuffer++ = pQueue-&gt;front();
    pQueue-&gt;pop();
}

return true;

}

int main(int argc, char *argv[])
{
FSOUND_SAMPLE *sample;
int iChannel;

// SELECT OUTPUT METHOD
FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);

// SELECT OUTPUT DRIVER (0 = default)
FSOUND_SetDriver(0);

// SELECT MIXER
//FSOUND_SetMixer(FSOUND_MIXER_QUALITY_AUTODETECT);

// INITIALIZE
if(!FSOUND_Init(OUTPUTRATE, 64, FSOUND_INIT_ACCURATEVULEVELS))
    printf(&quot;Error (%i): %s\n&quot;, __LINE__, FMOD_ErrorString(FSOUND_GetError()));

// SELECT INPUT DRIVER (0 = default)
if(!FSOUND_Record_SetDriver(0))
{
    printf(&quot;Error (%i): %s\n&quot;, __LINE__, FMOD_ErrorString(FSOUND_GetError()));
    FSOUND_Close();
}

printf(&quot;FSOUND Driver        : %s\n&quot;, FSOUND_GetDriverName(FSOUND_GetDriver()));
printf(&quot;FSOUND Record Driver : %s\n&quot;, FSOUND_Record_GetDriverName(FSOUND_Record_GetDriver()));

// CREATE SAMPLE TO RECORD TO
sample = FSOUND_Sample_Alloc(FSOUND_UNMANAGED, RECORDLEN, FSOUND_STEREO | FSOUND_16BITS , RECORDRATE, 255, 128, 255);

printf(&quot;Press any key to start recording!\n&quot;);
getch();

FSOUND_Sample_SetMode(sample, FSOUND_LOOP_NORMAL);

// START RECORDING (IN A LOOP)
if(!FSOUND_Record_StartSample(sample, TRUE))
{
    printf(&quot;Error (%i): %s\n&quot;, __LINE__, FMOD_ErrorString(FSOUND_GetError()));
    FSOUND_Close();
}

SoundQueue soundQueue;

do
{
    int recordpos, diff;
    static int oldrecordpos = 0;
    recordpos = FSOUND_Record_GetPosition();
    diff = recordpos - oldrecordpos;

    if(recordpos != oldrecordpos)
    {
      void* pRaw1 = NULL;
      void* pRaw2 = NULL;
      unsigned int iLen1, iLen2;

      // FETCH RAW SOUND DATA
      FSOUND_Sample_Lock(sample, oldrecordpos * sizeof(signed short), diff * sizeof(signed short), &amp;pRaw1, &amp;pRaw2, &amp;iLen1, &amp;iLen2);

      if(pRaw1 &amp;&amp; iLen1)
      {
        signed short* pData = (signed short*) pRaw1;
        unsigned int iChunkSize = iLen1 / sizeof(signed short);

        // PUSH CHUNKS OF SOUND DATA INTO A QUEUE
        for(int i = iChunkSize; i &gt; 0; i--)
            soundQueue.push(pData[i]);
      }

      if(pRaw2 &amp;&amp; iLen2)
      {
        signed short* pData = (signed short*) pRaw2;
        unsigned int iChunkSize = iLen2 / sizeof(signed short);     

        // PSUH CHUNKS OF SOUND DATA INTO A QUEUE
        for(int i = iChunkSize; i &gt; 0; i--)
            soundQueue.push(pData[i]);
      }

      FSOUND_Sample_Unlock(sample, pRaw1, pRaw2, iLen1, iLen2);
    }

    oldrecordpos = recordpos;
    Sleep(10);

} while (!kbhit());

// STOP RECORDING
FSOUND_Record_Stop();
FSOUND_Sample_Free(sample);
FSOUND_Close();

printf(&quot;Recording ended. Press any key to playback recorded data (by a stream).\n&quot;);
getch();

///////////////////////////////////////////////////////////////////////////////////////////////

FSOUND_STREAM  *stream;

// SELECT OUTPUT METHOD
FSOUND_SetOutput(FSOUND_OUTPUT_WINMM);

// SELECT SOUND CARD (0 = default)
FSOUND_SetDriver(0);

// INITIALIZE
if (!FSOUND_Init(OUTPUTRATE, 16, FSOUND_INIT_ACCURATEVULEVELS))
{
    printf(&quot;Error: %s\n&quot;, FMOD_ErrorString(FSOUND_GetError()));
    return 1;
}

// CREATE USER STREAM
stream = FSOUND_Stream_Create(streamcallback, OUTPUTRATE, FSOUND_NORMAL | FSOUND_16BITS | FSOUND_STEREO, OUTPUTRATE, (void *) &amp;soundQueue);
if(!stream)
{
    printf(&quot;Error: %s\n&quot;, FMOD_ErrorString(FSOUND_GetError()));
    return 1;
}

// PLAY STREAM
if (FSOUND_Stream_Play(FSOUND_FREE, stream) == -1)
{
    printf(&quot;Error: %s\n&quot;, FMOD_ErrorString(FSOUND_GetError()));
    return 1;
}

printf(&quot;Press any key to quit\n&quot;);
getch();

// CLEANUP AND SHUTDOWN
FSOUND_Stream_Close(stream);
FSOUND_Close();   
return 0;

}
[/code:3f4k3bbj]

Please help! 😕

  • You must to post comments
0
0

Hi Brett,

Yes, I tried to play it after recording was finished with FSOUND_PlaySound and it was all ok.

I made a printf in the callback which gave me this:
“In callback. len: 44100, count: 22050, pQueue.size(): 97020”

I am not sure what I should set lenbytes to in FSOUND_Stream_Create. I’ve noticed that if a too small number is set (ie 512, 1024), the callback is only run two times.

Any idea of what’s wrong with the lengths/pointer sizes? I am honestly lost! :(

  • You must to post comments
0
0

Nope, no loop number is set. I suppose the callback should loop forever then.
This should be rather simple, I just wanna record to a queue and then feed it to a stream.

Any other suggestions?

  • You must to post comments
0
0

Finally some progress:

I replaced this:
//soundQueue.push(pData[i]);

with this:
soundQueue.push(*pData++);

…in the for loops when locking the sound. Now the sound is perfect. The only problem is that I only hear half of the recorded sound, then the queue seems to be empty. If I playback the sample with FSOUND_PlaySound(…) I hear the full sample. Why this? 😮

About the FSOUND_LOOP_NORMAL flag:
No, I missed that. Now I have:

stream = FSOUND_Stream_Create(streamcallback, OUTPUTRATE, FSOUND_LOOP_NORMAL | FSOUND_NORMAL | FSOUND_16BITS | FSOUND_STEREO, OUTPUTRATE, (void *) &soundQueue);

I still hear only half of the sample, the difference now is that I can hear half the sample from any point (not always from the start).

Any help would be appreciated!

  • You must to post comments
0
0

were you ever able to fix the problem of partial playback???

  • You must to post comments
Showing 4 results
Your Answer

Please first to submit.