What I’m trying to do is write a “shoutcast-like” client/server MP3 streamer. I will be transmitting mp3-data from the server to the client via TCP/IP.
The mp3-data that is received by the client will be sent to a memory buffer, from which I plan to use FMOD to decode and play the mp3 data.
For development purposes (since I haven’t started work on the TCP/IP client) I am loading a full mp3 file to memory in one buffer, and using a second buffer which holds only a small block of data (this is to represent the buffer where the client stores the mp3 data). I have been able to get FMOD to play this buffer [once], but I cannot figure out a little-to-no latency method to update the contents of this buffer with the next block of audio data.
One method I attempted was to load the first block of data into the buffer, stream that, and when the stream finished playing, use an endofstream callback to refresh the data in that buffer. That code is as follows:
[code:2gim3bnf]signed char endcallback(FSOUND_STREAM *stream, void *buff, int len, int param)
// end of stream callback doesnt have a ‘buff’ value, if it doesnt it could be a synch point.
printf("\nSYNCHPOINT : \"%s\"\n", buff);
offset++; memcpy(data2, data + offset*samplesize, samplesize); data2[samplesize] = '\0'; FSOUND_Stream_SetTime(stream, 0); FSOUND_Stream_SetEndCallback(stream, endcallback, 0); channel = FSOUND_Stream_PlayEx(FSOUND_FREE, stream, NULL, TRUE); FSOUND_SetPaused(channel, FALSE);
This does a fine job at loading the data and playing it, except the audio does not play smoothly [it has at least a 500ms gap between blocks], due to the time involved with resetting where the stream is to be played.
I took a look at the Stream2 example, and modified it so that I can load in, using a similar method, a set of raw PCM wave data. The code follows:
signed char streamcallback(FSOUND_STREAM *stream, void *buff, int len, int param)
signed short *stereo16bitbuffer = (signed short *)buff;
memcpy(stereo16bitbuffer, data + offset*len, len); offset++; return 1;
This plays and updates with the block of data smoothly, appearing as if I were streaming from the file itself (or a large memory buffer).
From posts I’ve read, it appears that I need to use a ReadCallback to be able to load a buffer with real-time compressed data, but the only way to invoke that function is to do a Stream_OpenFile with a filename, and I am loading from memory, not a file.
Ideally, I would like to have a function similar my latter code segment that will be able to play any type of stream-compatible audio file, so I can update the buffer it reads from with the TCP/IP received data, and the audio can play back with very little latency.
Thanks in advance,
- menelfea asked 16 years ago
- You must login to post comments