0
0

Hi everyone…faced another kind of problem I can’t figure out myself…
Recently I’ve been working on a network voice chatting program which can send and receive raw pcm data in sockets. I found a sample program(server-client, socket programming, buffers of raw data) which worked fine, and began to modify it a little bit with fmod streaming functions(only the playback part). I searched for similar topics in the forum and found out that I should use the custom stream as written in ‘stream2’ example. Just for the player thread, I suppose it’s like this : define a streamcallback fumction -> make a custom stream and set the user parameter as a pointer to the received block of audio data(8 bit, mono, 22050Hz in my case). And here’s my code.
[code:2vpvbe57]
signed char F_CALLBACKAPI streamcallback(FSOUND_STREAM *stream, void *buff, int len, void *param)
{
LPWAVEHDR inHdr = (LPWAVEHDR) param;
LPSTR copiedBuf = (LPSTR) buff;
memcpy(copiedBuf, inHdr->lpData, len);
//len = supposed to be 2000 here
//should store the created data to buff
return 1;
}[/code:2vpvbe57]

Whenever the client receives a data block and it seems to contain the actual sound data, these two functions are called:
[code:2vpvbe57]
LRESULT PlaySound2::OnStartPlaying(WPARAM wParam, LPARAM lParam)
{ //wParam has the length info(2000 here)
MMRESULT mmReturn = 0; //lParam is the received wave header
wavHdr = (LPWAVEHDR)lParam; //wavHdr is a member variable of player thread
if(Playing==TRUE)
return FALSE; //this flag is checked before calling,

stream = FSOUND_Stream_Create(streamcallback, (int)wParam, FSOUND_8BITS | FSOUND_MONO, 22050, (void *)wavHdr);  //so stream is created only once when sound data is recognized for the first time
if (!stream)
{
    log.WriteString("\n Error occurred in PlaySound OnStartPlaying");
    return FALSE;
}
Playing = TRUE;

log.WriteString("\nOnStartPlaying called successfully, stream created");
return TRUE;

}

LRESULT PlaySound2::OnWriteSoundData(WPARAM wParam, LPARAM lParam)
{ //lParam is the pointer to current header data
wavHdr=(LPWAVEHDR)lParam; //update wavHdr with the newly received header
if(wavHdr==NULL)
return ERROR_SUCCESS;

if(!alreadyStarted)         //FSOUND_Stream_Play should be called once
{                  //so another flag is used
    if (FSOUND_Stream_Play(FSOUND_FREE, stream) == -1)
    {
        log.WriteString("\nError while playing stream");
        return ERROR_SUCCESS;
    }
    else 
    {
        log.WriteString("\n FSOUND_Stream_Play called");
        alreadyStarted = TRUE;
    }
}

log.WriteString("\n OnWriteSoundData called successfully. ");

return ERROR_SUCCESS;

}
[/code:2vpvbe57]
When run, I can only hear a strange noise. It sounds a little bit different when I speak to the microphone, but it’s all noise anyway. I guess something might be wrong in my way of feeding the data to the stream or the order that fmod functions appear, but not sure of anything. Can anybody help me find what I did wrong…?

  • You must to post comments
0
0

stream = FSOUND_Stream_Create(streamcallback, len, FSOUND_8BITS | FSOUND_UNSIGNED | FSOUND_MONO, 8000, (void *)wavHdr);
(I changed the sampling rate after posting, to 8000)
I think this is what you said, is it correct…?
I tried FSOUND_SIGNED and FSOUND_UNSIGNED but none worked…
What else could be thought causing the trouble…? Do you have any other recommendation…?

  • You must to post comments
0
0

are you sure that you are putting interleaved pcm data in the streamcallback :roll:

  • You must to post comments
0
0

Hmm…could you tell me a little more about what ‘interleaved’ means…? I’m not clear on the meaning yet…

At first the code was like this(wav data playback part, and it worked.):

[code:2ar8qscp]

LRESULT PlaySound1::OnStartPlaying(WPARAM wParam, LPARAM lParam)
{
MMRESULT mmReturn = 0;

if(Playing==TRUE)
    return FALSE;

log.WriteString("\n Starting playing");

    // open wavein device
     mmReturn = ::waveOutOpen( &m_hPlay, WAVE_MAPPER,
        &m_WaveFormatEx, ::GetCurrentThreadId(), 0, CALLBACK_THREAD);

    if(mmReturn )
        displayError(mmReturn,"PlayStart");   
    else
    {  
        Playing = TRUE;
        DWORD volume=0xffffffff;
        char str[100];

        if(!waveOutSetVolume(m_hPlay,volume))
        {
            volume=0;
            if(!waveOutGetVolume(m_hPlay,&volume))
            {
                wsprintf(str,"\n Volume is  %lx",volume);
                log.WriteString(str);
            }

        }  

    }          

return TRUE;
}

LRESULT PlaySound1::OnWriteSoundData(WPARAM wParam, LPARAM lParam)
{
MMRESULT mmResult = 0;

LPWAVEHDR lpHdr=(LPWAVEHDR)lParam;


if(lpHdr==NULL)
return ERROR_SUCCESS;

if(Playing)
{

    mmResult = ::waveOutPrepareHeader(m_hPlay, lpHdr, sizeof(WAVEHDR));

    if(mmResult)
    {
        log.WriteString("\nError while preparing header");
        return ERROR_SUCCESS;
    }

    mmResult = ::waveOutWrite(m_hPlay, lpHdr, sizeof(WAVEHDR));

    if(mmResult)
    {
        log.WriteString("\nError while writing to device");
        return ERROR_SUCCESS;

    }
}



return ERROR_SUCCESS;

}
[/code:2ar8qscp]

And this is from mmsystem.h:

/* wave data block header /
typedef struct wavehdr_tag {
LPSTR lpData; /
pointer to locked data buffer /
DWORD dwBufferLength; /
length of data buffer /
DWORD dwBytesRecorded; /
used for input only /
DWORD dwUser; /
for client’s use /
DWORD dwFlags; /
assorted flags (see defines) /
DWORD dwLoops; /
loop control counter /
struct wavehdr_tag FAR *lpNext; /
reserved for driver /
DWORD reserved; /
reserved for driver */
} WAVEHDR, *PWAVEHDR, NEAR *NPWAVEHDR, FAR *LPWAVEHDR;

So basically my idea was passing the lpData of the received LPWAVEHDR to fmod’s streamcallback.

stream = FSOUND_Stream_Create(streamcallback, (int)wParam, FSOUND_UNSIGNED | FSOUND_8BITS | FSOUND_MONO, 8000, (void *)wavHdr);

I think it shouldn’t be that difficult…but can’t find what I have to fix. Did I do something wrong with pointers…? Please help…Sorry for the msg being long…

Oh, BTW, I knew it was 8bit ’cause on the recording thread that was set up like this:

[code:2ar8qscp]
memset(&m_WaveFormatEx,0x00,sizeof(m_WaveFormatEx));

m_WaveFormatEx.wFormatTag=WAVE_FORMAT_PCM;
m_WaveFormatEx.nChannels=1;                 //mono
m_WaveFormatEx.wBitsPerSample=8;            //8 bits
m_WaveFormatEx.cbSize=0;
m_WaveFormatEx.nSamplesPerSec=SAMPLERSEC;       
m_WaveFormatEx.nBlockAlign=1; //(m_WaveFormatEx.wBitsPerSample/8)*m_WaveFormatEx.nChannels;

m_WaveFormatEx.nAvgBytesPerSec=SAMPLERSEC ;  //m_WaveFormatEx.nBlockAlign;

[/code:2ar8qscp]
SAMPLERSEC is 8000…I’ll try to find if I can do anything more. Thanks a lot.

  • You must to post comments
0
0

I tried the ‘^128’ in the receiving routine…

  1. the client receives the data block of 2000 characters here:

rcount=sockclt.Receive(buff,size);

  1. after this I make a LPWAVEHDR named lpHdr using buff…

for(i=20,j=0;j<length;i++,j++)
lpHdr->lpData[j]=buff[i]^128; //lpData : pointer to the locked data buffer. buff[20] is the first, buff[0]~buff[19] has the sender / length info

This is done before the stream is created.

Wow…now the loud noise has gone, but what happens is, for example, if I say ‘blah’ like 3 times, it repeats a little broken ‘blah’ about 10 times.
I feel like getting closer, thanks so much…do you have any ideas on what I should do more…?

  • You must to post comments
Showing 4 results
Your Answer

Please first to submit.