Skip to main content

Suggested APIs for streaming and splicing audio clips

6 replies [Last post]
arorholt
Offline
Joined: 2010-04-29

There has been an interest in playing and splicing audio clips through the MPEOS sound driver. This is a suggestion for new MPEOS sound APIs that will allow for continuous play of audio. These APIs also allow seamless splicing of audio clips.

/**
* mpeos_sndCreateStream()
*
* Creates a streaming sound object.
*
* @param type MIME type of the sound data
* @param streamData pointer to function which will supply stream data
* @param sound pointer to a mpe_SndSound
*
* @return MPE_SND_ERROR_EMIME if streaming of type is not supported.
* @return MPE_ENOMEM if memory cannot be allocated.
* @return MPE_SUCCESS if the mpe_SndSound was created successfully.
*/
mpe_Error mpeos_sndCreateStream(const char *type, mpe_Bool
(*streamData)(const char *data, uint32_t *size), mpe_SndSound *sound)

User of API will provide a function with this prototype:

/**
* streamData
*
* Supplies stream data to the MPEOS snd API. Will be called as often
as required
* to prevent underflow, but the implementation of this function should
NOT block.
*
* @param data pointer to the location to which sound data should be
written.
* @param size as input parameter gives the maximum size of the buffer,
* as ouput parameter gives the number of bytes written.
*
* @return MPE_TRUE if there is more stream data to be written.
* @return MPE_FALSE if stream data is exhausted.
*/

/**
* mpeos_sndPlayStream()
*
* Starts playback of the streaming sound, data will be requested via
the registered function.
* Note that sound file header data (if any) should be supplied in the
first requested buffer.
*
* @param device handle of the sound device to start playback
* @param sound handle of sound to play
* @param handle event dispatch handle to use for delivering native
* events back to Java.
* @param playback pointer that will be assigned to a valid playback
* handle if successful.
*
* @return MPE_EINVAL if any of the handles or pointers are NULL.
* @return MPE_ENOMEM if memory cannot be allocated.
* @return MPE_SND_ERROR_ERES if native resources cannot be obtained.
* @return MPE_SUCCESS if successful.
*/
mpe_Error mpeos_sndPlayStream(mpe_SndDevice device, mpe_SndSound sound,
mpe_EdHandle handle, mpe_SndPlayback *playback)

Example usage:

char *pcmData = NULL;
uint32_t dataRemaining = 0;
mpe_Bool continueStreaming = MPE_TRUE;

/* To avoid these globals, I'm open to the possibility of passing an
extra void* pointer in with the call to mpeos_sndCreateStream, which
will then be passed back to the call of streamData */

mpe_Bool streamData(const char *data, uint32_t *size)
{
uint32_t copySize = 0;
mpe_Bool ret = MPE_TRUE;

if (data == NULL || size == 0 || continueStreaming != MPE_TRUE)
return MPE_FALSE;

if (dataRemaining == 0 || pcmData == NULL)
return MPE_FALSE;

if (dataRemaining < *size)
{
copySize = dataRemaining;
*size = copySize;
ret = MPE_FALSE;
}
else
{
copySize = *size;
}

memcpy(data, pcmData, copySize);
dataRemaining -= copySize;
data += copySize;

return ret;
}

void startStream(mpe_SndDevice device, char *data, uint32_t size,
mpe_EdHandle ed_handle)
{
mpe_SndSound stream = NULL;
mpe_SndPlayback playback = NULL;
mpe_Error ret;

pcmData = data;
dataRemaining = size;
mpe_Bool continueStreaming = MPE_TRUE;

ret = mpeos_sndCreateStream("audio/x-aiff", streamData, &stream);
if (ret != MPE_SUCCESS)
{
/* HANDLE ERROR */
}

ret = mpeos_sndPlayStream(device, stream, ed_handle, &playback);
if (ret != MPE_SUCCESS)
{
/* HANDLE ERROR */
}

/* Stop streaming after 20 seconds, or data runs out, whichever is
* sooner. NB: this need not be from this context, could be a
* different function. */
sleep(20);
continueStreaming = MPE_FALSE;
}

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
arorholt
Offline
Joined: 2010-04-29

This is more readable:
mpeos_sndCreateStream(const char *type, mpe_Bool (*streamData)(const char *data, uint32_t *size), mpe_SndSound *sound)
Parameters:
type MIME type of the sound data
streamData pointer to function which will supply stream data
sound pointer to a mpe_SndSound
Return:
MPE_SND_ERROR_EMIME if streaming of type is not supported.
MPE_ENOMEM if memory cannot be allocated.
MPE_SUCCESS if the mpe_SndSound was created successfully.

User of API will provide a function with this prototype:

mpe_Bool streamData(const char *data, uint32_t *size)
Supplies stream data to the MPEOS snd API. Will be called as often as required to prevent underflow, but the implementation of this function should NOT block.
Parameters:
data pointer to the location to which sound data should be written.
size as input parameter gives the maximum size of the buffer, as ouput parameter gives the number of bytes written.
Return:
MPE_TRUE if there is more stream data to be written.
MPE_FALSE if stream data is exhausted.

mpe_Error mpeos_sndPlayStream(mpe_SndDevice device, mpe_SndSound sound, mpe_EdHandle handle, mpe_SndPlayback *playback)
Starts playback of the streaming sound, data will be requested via the registered function.
Note that sound file header data (if any) should be supplied in the first requested buffer.
Parameters:
device handle of the sound device to start playback
sound handle of sound to play
handle event dispatch handle to use for delivering native events back to Java.
playback pointer that will be assigned to a valid playback handle if successful.
Return:
MPE_EINVAL if any of the handles or pointers are NULL.
MPE_ENOMEM if memory cannot be allocated.
MPE_SND_ERROR_ERES if native resources cannot be obtained.
MPE_SUCCESS if successful.

Example usage:

char *pcmData = NULL;
uint32_t dataRemaining = 0;
mpe_Bool continueStreaming = MPE_TRUE;
(To avoid these globals, we could pass an extra void* pointer in with the call to mpeos_sndCreateStream, which will then be passed back to the call of streamData)

mpe_Bool streamData(const char *data, uint32_t *size)
{
uint32_t copySize = 0;
mpe_Bool ret = MPE_TRUE;

if (data == NULL || size == 0 || continueStreaming != MPE_TRUE)
return MPE_FALSE;

if (dataRemaining == 0 || pcmData == NULL)
return MPE_FALSE;

if (dataRemaining lt *size)
{
copySize = dataRemaining;
*size = copySize;
ret = MPE_FALSE;
}
else
{
copySize = *size;
}

memcpy(data, pcmData, copySize);
dataRemaining -= copySize;
data += copySize;

return ret;
}

void startStream(mpe_SndDevice device, char *data, uint32_t size,
mpe_EdHandle ed_handle)
{
mpe_SndSound stream = NULL;
mpe_SndPlayback playback = NULL;
mpe_Error ret;

pcmData = data;
dataRemaining = size;
mpe_Bool continueStreaming = MPE_TRUE;

ret = mpeos_sndCreateStream("audio/x-aiff", streamData, &stream);
if (ret != MPE_SUCCESS)
{
/* HANDLE ERROR */
}

ret = mpeos_sndPlayStream(device, stream, ed_handle, &playback);
if (ret != MPE_SUCCESS)
{
/* HANDLE ERROR */
}

/* Stop streaming after 20 seconds, or data runs out, whichever is
* sooner. NB: this need not be from this context, could be a
* different function. */
sleep(20);
continueStreaming = MPE_FALSE;
}

greg80303
Offline
Joined: 2008-07-03

To avoid having your posts show up as a single line, you have to remove all "<" and ">" characters. I am not sure how to escape these characters in the forums at this time -- I just end up removing them.

cpratt
Offline
Joined: 2008-12-18

What Greg's saying is that the forum preprocessor removes all formatting if you include a single "<" or ">" and ends up making the post a single line.

"& lt ;" and "& gt ;" (take out the spaces) is "<" and ">", respectively.

cpratt
Offline
Joined: 2008-12-18

The HN extension allows for the presentation of streaming media (via the mpeos_hnStreamOpen()/mpeos_hnPlaybackStart() APIs).

Is this intended to add streaming without utilizing the HN extension?

arorholt
Offline
Joined: 2010-04-29

The HN extensions can be used for this, but it is a bit of an overkill to set up all of this if all you want is to play out memory buffers with sound.

SteveFlores
Offline
Joined: 2011-12-13

can you give detailed information about HN extensions? I heard that there are changes with the HN Extension Spec document to support live streaming, but I can't find detailed information right now