How to stop an audio stream

I’m able to play a PCM stream, copying 320 bytes every time the low-level IRQ is called by the OS. The questions is: how to stop playing?

I don’t think calling adl_audioStop() inside the IRQ is a good solution. The example in the documentation lacks this point.

I’m thinking to set a global flag and fill the buffer with null values and check the flag inside a function called at a regular interval. When this function detects the flag, it call adl_audioStop().
Is there a more elegant and better method?

Do you mean “stop” as in finish when it’s complete, or to do a premature abort while playing :question:

Hiya,

I just call adl_audioStop() at the time I want the stream to stop - usually an event handler (i.e. a different DTMF tone has been pressed) but NOT from inside the IRQ handler.

I’ve had a quick look at my code, and it appears that the low IRQ is responsible for pushing the samples out the audio channel, and the high IRQ is responsible for setting up which data array is to be played (i.e. that’s where I call adl_audioStreamPlay()).

ciao, Dave

I mean stop when the stream is complete. My low-level interrupt is always called… how to stop the playing?

I have a const array with PCM samples. In the low-level IRQ I memcpy 320 bytes from array to stream buffer, set BufferReady flag to TRUE and return FALSE.
The stream is 1000 bytes long (500 16-bits samples). After adl_audioStreamPlay() the IRQ function is called 3 times and I copy 3*320=960 bytes.
The 4th time I have to copy only 40 bytes to the stream buffer (I have no more than 1000 bytes) and I have to say to play just for additional 40 bytes and stop. How to achieve this?

I can fill the stream buffer with 40 useful bytes and 320-40=280 null bytes so nothing is played after the last useful sample. Anyway the problem remains: after the 4th slot, the IRQ is called again for the 5th time and so on…

I call adl_audioStreamPlay() from main task (as in Sierra example) and not from high IRQ.

It seems you call adl_audioStop() when an event occurs (a key is pressed or a DTMF tone is detected), so when your event handler is called by the operating system. In my case I want to call adl_audioStop() when I have no more samples and I know this only in low-level IRQ function.

Here it is my code:

const u16 audiostream[] = {
  0x0000U, 0xFFFFU, 0x0000U, 0x0001U, 0xFFFFU, 0x0000U, 0x0000U, 0x0000U,
  0x0000U, 0xFFFFU, 0x0001U, 0x0000U, 0xFFFFU, 0x0001U, 0xFFFFU, 0x0000U,
  ...
};

s32 audio_handle;
s32 bufsize;

bool
irq_lowlevel(adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel, adl_irqEventData_t *Data)
{
  static int x;
  if (x < sizeof(audiostrem)) {
    // Here I suppose sizeof(audiostream) is a multiple of bufsize=320
    wm_memcpy(streambuf, (const char *)&audiostream[x], bufsize);
    x += bufsize;
    *((adl_audioStream_t *)Data->SourceData)->BufferReady = TRUE;
  } else {
    // I have no more samples... how to stop the playing?
  }
  return FALSE;
}

void main_task ( void )
{
  audio_handle = adl_audioSubscribe (ADL_AUDIO_SPEAKER, audio_handler, ADL_AUDIO_RESOURCE_OPTION_FORBID_PREEMPTION);
  s32 irq_handle;
  irq_handle = adl_irqSubscribe(irq_lowlevel, ADL_IRQ_NOTIFY_LOW_LEVEL,
                        0,		/* Priority level */
                        0);		/* Options (ignored for low level IRQs) */
  adl_audioGetOption (audio_handle, ADL_AUDIO_PCM_8K_16B_MONO_BUFFER_SIZE, &bufsize);
  streambuf = adl_memGet(bufsize);
  adl_audioStreamPlay(audio_handle, ADL_AUDIO_PCM_MONO_8K_16B, irq_handle, 0, streambuf);
}

I noticed there is a demo project named pcm_record_and_play. After studying it, I understood I need both low- and high-level IRQs. The low-level is responsible to push new samples into the playing buffer. If there aren’t more samples, the IRQ function return TRUE to notify the high-level IRQ. The high-level function is automatically called and adl_audioStop() can be called.

The only thing I can’t understand is how to face the situation where int the last low-level IRQ call I don’t have other 320 bytes of sample, but only 100. I want to play those 100 bytes, but no more. I think I have to “pad” the playing buffer with zeros.

I applied the same strategy on playing audio stream AMR-NB compressed (I used ffmpeg to convert from wav to AMR-NB). It works because I can hear the correct sound output from the speaker, but there’s a problem. There’s just a difference with PCM: with AMR streams I can decide the buffer size and set it through adl_SetOption(). I can decide to use the same size of the stream, so the low-level IRQ is called just one time.
After playing all the stream, the ARM core crashed with Data Abort exception and the firmware resets.

Could somone test the following code?

#define DECLARE_CALL_STACK(X)   (X)
const adl_InitTasks_t adl_InitTasks [] = {
    {main_task, DECLARE_CALL_STACK(1024), "main", 2},
    {0, 0, 0, 0}		/* Mark end of list */
};
ADL_DECLARE_LOWIRQ_STACK(1024);
ADL_DECLARE_HIGHIRQ_STACK(1024);

const u8 audiostream[] = {
		// 0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A,		// Header from AMR file
		0x04, 0x33,
		0x00, 0x4F, 0xF2, 0x3D, 0x08, 0x33, 0x99, 0xA0,
		0x62, 0x2E, 0x0E, 0x04, 0x15, 0x98, 0xAF, 0xF2,
		0x06, 0xE0, 0xA4, 0xDD, 0x9B, 0x2F, 0x88, 0x3E,
		0x04, 0x92, 0xEA, 0x4B, 0xF0, 0x0B, 0xA5, 0x15,
		0x0B, 0x27, 0x34, 0xDC, 0x1E, 0x04, 0x94, 0x84,
		0xD3, 0xC0, 0x46, 0x5F, 0x45, 0x98, 0x2C, 0xF2,
		0x69, 0xD6, 0x04, 0x70, 0xEA, 0x93, 0xC0, 0x18,
		0x3A, 0x7B, 0x91, 0x5A, 0xB9, 0xEA, 0x44, 0x04,
		0x36, 0x1E, 0xC7, 0xC0, 0x14, 0x26, 0xC9, 0x5A,
		0x0F, 0x5F, 0x6A, 0xE8, 0x04, 0x92, 0x00, 0xB7,
		0xB2, 0x20, 0x9B, 0x49, 0x1B, 0x68, 0x26, 0xED,
		0xD2, 0x04, 0x23, 0x1E, 0x37, 0x71, 0x0B, 0x9B,
		0x05, 0x21, 0xCA, 0x44, 0xAB, 0x62, 0x04, 0x23,
		0x00, 0xF3, 0xD0, 0x06, 0x35, 0xB5, 0xAC, 0x5F,
		0x07, 0x04, 0x5A, 0x04, 0xFD, 0xF3, 0xD0, 0xF6,
		0xF7, 0x77, 0xDE, 0x78, 0xFC, 0xCD, 0xEE, 0x2E,
		0x04, 0x29, 0x92, 0x27, 0x0F, 0x91, 0x91, 0xED,
		0x17, 0x10, 0xD4, 0x0A, 0xE4, 0x04, 0x1F, 0xC6,
		0x27, 0x08, 0xE8, 0x97, 0xB3, 0x8F, 0xC5, 0xB3,
		0x46, 0x90, 0x04, 0x95, 0xE8, 0x1C, 0x3C, 0xF5,
		0x6D, 0x33, 0xA1, 0xE9, 0x74, 0x0A, 0xF8, 0x04,
		0x34, 0x4B, 0x39, 0x6E, 0xD2, 0xF7, 0xDC, 0xFA,
		0x69, 0x01, 0xFF, 0x0A, 0x04, 0xA0, 0x2D, 0x32,
		0x6E, 0xCD, 0xDB, 0xC8, 0x39, 0x59, 0xD2, 0x88,
		0x4C, 0x04, 0xAD, 0xF1, 0x32, 0x2F, 0xEA, 0xD3,
		0x4E, 0xD0, 0xE9, 0xA4, 0xC1, 0x14, 0x04, 0x42,
		0xF3, 0x25, 0xAD, 0xE0, 0xE6, 0x97, 0xE0, 0x6E,
		0x98, 0x3C, 0x32, 0x04, 0x47, 0x5F, 0x22, 0x9D,
		0xF3, 0x9F, 0xAA, 0x25, 0x22, 0x61, 0x19, 0x04,
		0x04, 0xB5, 0xF0, 0x23, 0xEE, 0xE3, 0x14, 0x4A,
		0x5A, 0xA3, 0x02, 0xCA, 0xB0, 0x04, 0xB5, 0x17,
		0x33, 0xC9, 0xD3, 0x67, 0x30, 0x15, 0x21, 0x12,
		0x02, 0xD4, 0x04, 0x71, 0xD0, 0x40, 0x2D, 0xF4,
		0xC6, 0xA4, 0x13, 0xB7, 0x39, 0xDE, 0xAC, 0x04,
		0xB5, 0xCA, 0x23, 0xAF, 0xF7, 0x30, 0xE8, 0xE2,
		0x8C, 0x57, 0x17, 0xDC, 0x04, 0x48, 0xC4, 0x2A,
		0xFF, 0xB1, 0xC6, 0x73, 0x44, 0x50, 0x59, 0xAA,
		0x04, 0x04, 0xB5, 0xCA, 0x33, 0xFE, 0x91, 0xD5,
		0x82, 0x12, 0x20, 0x8E, 0xEA, 0x26, 0x04, 0xAB,
		0xB1, 0x48, 0xFE, 0x80, 0x7F, 0x78, 0x93, 0x8E,
		0x0F, 0x15, 0x94, 0x04, 0xD3, 0x10, 0x6A, 0x43,
		0xCB, 0x41, 0x75, 0x02, 0x25, 0x32, 0x3D, 0x7C,
		0x04, 0x3F, 0x45, 0x3B, 0xFB, 0xFB, 0x2E, 0xEA,
		0x67, 0x8E, 0xB5, 0x59, 0x3A, 0x04, 0xED, 0x41,
		0x80, 0x1F, 0xCF, 0x4B, 0x53, 0x89, 0x19, 0x43,
		0x88, 0x40, 0x04, 0x57, 0xD7, 0xF3, 0x7F, 0xF8,
		0x9A, 0x0F, 0x73, 0xA2, 0x62, 0x60, 0x0C, 0x04,
		0x1D, 0x3C, 0xCC, 0xFC, 0xC8, 0x65, 0x8B, 0x4F,
		0x59, 0xA5, 0x61, 0xBE, 0x04, 0xD4, 0x77, 0x40,
		0x9F, 0xFB, 0xA3, 0x65, 0x4D, 0xF6, 0xEE, 0x4F,
		0x1C, 0x04, 0xAE, 0xBA, 0x43, 0x0F, 0xE9, 0xEF,
		0x97, 0xBD, 0x1A, 0x37, 0xA4, 0x78, 0x04, 0xB5,
		0x60, 0x3E, 0xAE, 0xC0, 0xAF, 0x97, 0x32, 0xB9,
		0xE0, 0x41, 0x7A, 0x04, 0xB5, 0x10, 0x3A, 0xAE,
		0xE2, 0x9D, 0xD0, 0xD7, 0x83, 0x19, 0x8E, 0x40,
		0x04, 0xB5, 0xF0, 0x3B, 0xAC, 0xAE, 0xDF, 0x78,
		0x0C, 0x79, 0xE6, 0x5B, 0x62, 0x04, 0xE7, 0x33,
		0x38, 0xAC, 0xB4, 0xBD, 0x97, 0xD2, 0xAC, 0x52,
		0xA2, 0xA2, 0x04, 0xD9, 0x73, 0x36, 0xAD, 0xF1,
		0x56, 0x98, 0xAC, 0x92, 0xA2, 0x46, 0x68, 0x04,
		0x8E, 0xC6, 0x35, 0xAD, 0xE4, 0x9C, 0xE7, 0xB4,
		0x58, 0x50, 0xF5, 0xA2, 0x04, 0xD9, 0x73, 0x36,
		0xAE, 0xE2, 0x94, 0xE4, 0xEE, 0xB6, 0xC5, 0x58,
		0x9C, 0x04, 0xD9, 0x42, 0x36, 0xAB, 0xE3, 0x94,
		0x6A, 0xC2, 0xC8, 0x2B, 0x20, 0x9C, 0x04, 0xB5,
		0xF0, 0x36, 0x5D, 0xED, 0xE2, 0x10, 0x3B, 0x28,
		0x82, 0x04, 0xE2, 0x04, 0xB5, 0x34, 0x32, 0xDD,
		0x92, 0xD4, 0x24, 0x9C, 0x25, 0x61, 0xF5, 0xB8,
		0x04, 0xD9, 0x10, 0x43, 0xFD, 0x9D, 0x88, 0xD9,
		0x87, 0x8F, 0x64, 0xAD, 0x9E, 0x04, 0x3C, 0xEB,
		0xFC, 0x2F, 0x3E, 0xB4, 0x29, 0xC7, 0x2C, 0x1A,
		0x78, 0x9E, 0x04, 0x68, 0xF3, 0x46, 0x4E, 0xF7,
		0x14, 0x5C, 0x1A, 0x0E, 0xBF, 0xB1, 0x4E, 0x04,
		0x55, 0x11, 0x9F, 0xCF, 0x82, 0x0E, 0xE5, 0x0A,
		0x40, 0x16, 0x63, 0x26, 0x04, 0xD4, 0x1F, 0x38,
		0xBF, 0xF5, 0xE2, 0x22, 0x42, 0xC2, 0x8F, 0xE0,
		0x64, 0x04, 0x42, 0x1D, 0x2E, 0x6C, 0xBE, 0xE1,
		0xD9, 0xCA, 0xCC, 0x0A, 0x47, 0xE4, 0x04, 0x95,
		0xC1, 0x2E, 0x9F, 0xE3, 0xF3, 0x27, 0xDB, 0xDB,
		0x9F, 0x51, 0xA4, 0x04, 0x54, 0x27, 0x32, 0xBD,
		0xEE, 0x0A, 0xA8, 0x5C, 0x0C, 0x04, 0xEB, 0x50,
		0x04, 0x1E, 0xC1, 0x29, 0xBF, 0xE0, 0xDB, 0xD6,
		0xB3, 0xFC, 0x1C, 0xC1, 0x5A, 0x04, 0xD9, 0x28,
		0x32, 0xFE, 0x35, 0x1B, 0xC0, 0xFB, 0xA4, 0x91,
		0xC7, 0x98, 0x04, 0x1E, 0xC8, 0x30, 0xFF, 0xFF,
		0xB7, 0x6E, 0x3C, 0xA1, 0xD6, 0x31, 0xAA, 0x04,
		0xE7, 0x01, 0x36, 0xFD, 0x96, 0x90, 0x5D, 0x5B,
		0xF3, 0xB0, 0x97, 0x8A, 0x04, 0x42, 0xDC, 0x48,
		0x5F, 0xD5, 0xB7, 0x5A, 0xCD, 0x7D, 0x70, 0x43,
		0x4E, 0x04, 0x42, 0xDC, 0x3F, 0xBE, 0xF8, 0xD0,
		0xE8, 0x10, 0x27, 0x9E, 0xD2, 0x52, 0x04, 0x42,
		0x0F, 0x46, 0xED, 0xF5, 0xC7, 0xB1, 0x85, 0xE4,
		0x69, 0xB3, 0x68, 0x04, 0x8F, 0x61, 0x4E, 0xFF,
		0xE5, 0x81, 0x61, 0xC8, 0x38, 0x13, 0x22, 0x42,
		0x04, 0xD3, 0xFC, 0x5E, 0x7B, 0xFD, 0xAA, 0x7E,
		0xBC, 0x86, 0x61, 0x1C, 0xFC, 0x04, 0x95, 0x63,
		0x5F, 0xCB, 0x90, 0xDF, 0x34, 0x88, 0xB6, 0x24,
		0xA6, 0x20, 0x04, 0xB5, 0xF9, 0x6B, 0xFD, 0x9C,
		0x63, 0x46, 0x20, 0x3A, 0x41, 0x24, 0xAC, 0x04,
		0xD4, 0xA7, 0x6F, 0xCF, 0x97, 0xDC, 0x71, 0xE1,
		0xAB, 0xB1, 0x3A, 0x9C, 0x04, 0x95, 0x40, 0x77,
		0xF8, 0x88, 0x22, 0xB3, 0x8F, 0x94, 0xA8, 0xC6,
		0x04, 0x04, 0xAB, 0x38, 0x67, 0xF9, 0x3B, 0x86,
		0x35, 0x90, 0xC8, 0x14, 0x9F, 0x60, 0x04, 0xB5,
		0x9C, 0x6C, 0xE4, 0x7B, 0x4C, 0xD4, 0x7C, 0x2C,
		0x8E, 0x0D, 0x50, 0x04, 0x95, 0x08, 0x6B, 0xC3,
		0x16, 0xEA, 0x45, 0xBB, 0xC5, 0xCD, 0x71, 0x70,
		0x04, 0x95, 0xFC, 0xF0, 0xF3, 0x0B, 0x3A, 0x74,
		0x39, 0x6C, 0x64, 0x9D, 0xCC, 0x04, 0xE7, 0x26,
		0xF3, 0x03, 0x0E, 0xF7, 0x3A, 0x25, 0xD1, 0x09,
		0x2E, 0x54, 0x04, 0x36, 0x3C, 0x34, 0x35, 0xFF,
		0xA0, 0xBA, 0xE1, 0x41, 0x7A, 0x4C, 0x14, 0x04,
		0x3B, 0x42, 0x04, 0x2F, 0x8B, 0x63, 0x64, 0x0E,
		0x8B, 0x36, 0xBB, 0x1A, 0x04, 0xD4, 0xEC, 0x40,
		0xCF, 0xEA, 0x65, 0xAE, 0xB8, 0x44, 0xF4, 0x6B,
		0xEE, 0x04, 0xD3, 0x1D, 0x6A, 0xDF, 0x93, 0x67,
		0xAA, 0x8E, 0x60, 0xC8, 0x82, 0x00, 0x04, 0xD3,
		0xC7, 0x6A, 0xAB, 0x9A, 0xFC, 0x53, 0x24, 0xE2,
		0x86, 0x8A, 0x92, 0x04, 0xF3, 0xC7, 0x6E, 0x9B,
		0xC3, 0xA7, 0x2A, 0xE7, 0xDC, 0x7B, 0x84, 0x4A,
		0x04, 0xB5, 0xF1, 0x6E, 0xBB, 0x32, 0xFA, 0x24,
		0xA0, 0xED, 0x41, 0x6A, 0x62, 0x04, 0xF3, 0x4B,
		0x75, 0xBB, 0x9E, 0xC0, 0x69, 0x5B, 0x54, 0x80,
		0x6F, 0x54, 0x04, 0xF3, 0x09, 0x77, 0xFC, 0x73,
		0x1E, 0xBB, 0x11, 0x75, 0x31, 0xBC, 0xE8, 0x04,
		0xF3, 0x37, 0x77, 0xF0, 0x0B, 0x07, 0x55, 0xD9,
		0xF8, 0x09, 0x2E, 0x4E, 0x04, 0xFE, 0x3C, 0x3F,
		0xBE, 0x0D, 0x2C, 0x33, 0x91, 0x87, 0x95, 0x14,
		0x44, 0x04, 0x34, 0x56, 0xAE, 0xF0, 0x2D, 0x19,
		0xE3, 0xAD, 0xFC, 0x75, 0x36, 0x4E, 0x04, 0xFF,
		0x18, 0x93, 0xC0, 0x17, 0x13, 0xC5, 0x9A, 0xD1,
		0x47, 0xE1, 0x1A, 0x04, 0x58, 0xEA, 0x8F, 0xF0,
		0x07, 0x06, 0x85, 0xFF, 0xE1, 0x04, 0xD2, 0xD2,
};
size_t audiostream_len = sizeof(audiostream);

s32 speaker_handle;
s32 bufsize;
void *streambuf;

bool
irq_lowlevel(adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel, adl_irqEventData_t *Data)
{
  static int x;
  if (x >= audiostream_len) return TRUE;  /* Notify high-level IRQ */
  wm_memcpy(streambuf, (const char *)&audiostream[x], bufsize);
  x += bufsize;
  *((adl_audioStream_t *)Data->SourceData)->BufferReady = TRUE;
  return FALSE;		/* Don't notify high level IRQ */
}

bool
irq_highlevel(adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel, adl_irqEventData_t *Data)
{
	adl_audioStop(speaker_handle);
	return FALSE;		/* Return value is ignored in high-level IRQ */
}

void
main_task (void)
{
  s32 irq_handle;
  irq_handle = adl_irqSubscribe(irq_lowlevel, ADL_IRQ_NOTIFY_LOW_LEVEL,
                        0,		/* Priority level */
                        0);		/* Options (ignored for low level IRQs) */

  s32 irq_high_handle;
  irq_high_handle = adl_irqSubscribe(irq_highlevel, ADL_IRQ_NOTIFY_HIGH_LEVEL,
                        0,		/* Priority level */
                        0);		/* Options (ignored for low level IRQs) */

  bufsize = audiostream_len;
  // Set Mixed voice option
  adl_audioSetOption (audio_handle, ADL_AUDIO_AMR_MIXED_VOICE, FALSE);
  // Set Codec Rate
  adl_audioSetOption (audio_handle, ADL_AUDIO_AMR_SPEECH_CODEC_RATE, ADL_AUDIO_AMR_RATE_4_75);
  // Set Buffer Size
  adl_audioSetOption (audio_handle, ADL_AUDIO_AMR_BUFFER_SIZE, bufsize);
  // Memory allocation
  streambuf = adl_memGet(bufsize);
  adl_audioStreamPlay(audio_handle, ADL_AUDIO_AMR, irq_handle, irq_high_handle, streambuf);
}

Hiya,

From a quick look, I think that this line is wrong:

size_t audiostream_len = sizeof(audiostream);

Try changing to this:

size_t audiostream_len = sizeof(audiostream)/sizeof(audiostream[0]);

I’ll try and run the code when I get to work.

Ciao, Dave

Hello David, thank you for your answer.

I can’t test your suggestion just now, but I don’t think this will solve my issue. audiostream is defined as an array of const u8 that is defined as uint8_t that is defined as unsigned char. So sizeof(audiostream[0]) is 1. Your expression is more elegant, but identical to the mine.

Hiya,

I’ve just spent an hour or so on your code, and after tidying up a few minor errors in what you posted I can confirm that I am seeing the same RTK error.

According to the backtraces, there is a bad memory access error occurring at this line:

*( (adl_audioStream_t *)Data->SourceData)->BufferReady = TRUE;

in the low level IRQ handler.

I’m scratching my head about this - the Data pointer is created/managed by the irq subscription process. I will admit that I used PCM, rather than AMR - although using AMR has been on my radar because of the smaller data footprint.

I’ve got to put it down for the moment - but will keep thinking it over.

ciao, Dave

Hmmm…, I’m interested in those few minor errors.

I think I have to contact FAE of Sierra.

Hiya,

Mostly compiler errors, although there were a couple of program errors.

Compiler errors:

  1. I needed to predefine the main_task() function before declaring the adl_InitTasks table (undefined function error)
  2. You had declared (and used in the IRQ functions) the variable speaker_handle. However, in all the adl_audioXXX() setup functions in main you had used the undeclared variable audio_handle

Program errors:

  1. in the main_task() you had never called adl_audioSubscribe() to subscribe to the audio handle
  2. in the irq_lowlevel() you had never explicity set the static x variable to a value. I know the compiler is supposed to implicitly initialize static variables to zero - but you never know what’s going on under the hood!

It’s also a good idea to check the return values of subscriptions (irq, audio etc) for errors and let yourself know. I’ve put a few TRACE() macro calls in the code as well to output some info during the program run.

I agree with you, we need to hear from SiWi about this one…

I’ve attached my version (which has the same issue as you have!) below.

OK: I’ve inserted the code inline as the Forum is not letting me post attachments…

#include "adl_global.h"

void main_task( void );

/***************************************************************************/
/*  Mandatory variables                                                    */
/*-------------------------------------------------------------------------*/
/*  wm_apmCustomStackSize                                                  */
/*-------------------------------------------------------------------------*/
/***************************************************************************/
//const u16 wm_apmCustomStackSize = 1024;

const u32 adl_InitIRQLowLevelStackSize =  4096;
const u32 adl_InitIRQHighLevelStackSize = 4096;

/***************************************************************************/
/*  Tasks declaration table                                                */
/***************************************************************************/

/**
 * @brief Task Declaration Table
 */

const adl_InitTasks_t adl_InitTasks [] =
{
    { main_task,  3*1024, "MAIN",    1 }, // Main task
    { NULL, 0, NULL, 0 }
};

#ifdef __DO_NOT_COMPILE__
#define DECLARE_CALL_STACK(X)   (X)
const adl_InitTasks_t adl_InitTasks [] = {
	{main_task, DECLARE_CALL_STACK(1024), "main", 2},
	{0, 0, 0, 0}      /* Mark end of list */
};
ADL_DECLARE_LOWIRQ_STACK(4096);
ADL_DECLARE_HIGHIRQ_STACK(4096);

#endif

const u8 audiostream[] = {
	  // 0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A,      // Header from AMR file
	  0x04, 0x33,
	  0x00, 0x4F, 0xF2, 0x3D, 0x08, 0x33, 0x99, 0xA0,
	  0x62, 0x2E, 0x0E, 0x04, 0x15, 0x98, 0xAF, 0xF2,
	  0x06, 0xE0, 0xA4, 0xDD, 0x9B, 0x2F, 0x88, 0x3E,
	  0x04, 0x92, 0xEA, 0x4B, 0xF0, 0x0B, 0xA5, 0x15,
	  0x0B, 0x27, 0x34, 0xDC, 0x1E, 0x04, 0x94, 0x84,
	  0xD3, 0xC0, 0x46, 0x5F, 0x45, 0x98, 0x2C, 0xF2,
	  0x69, 0xD6, 0x04, 0x70, 0xEA, 0x93, 0xC0, 0x18,
	  0x3A, 0x7B, 0x91, 0x5A, 0xB9, 0xEA, 0x44, 0x04,
	  0x36, 0x1E, 0xC7, 0xC0, 0x14, 0x26, 0xC9, 0x5A,
	  0x0F, 0x5F, 0x6A, 0xE8, 0x04, 0x92, 0x00, 0xB7,
	  0xB2, 0x20, 0x9B, 0x49, 0x1B, 0x68, 0x26, 0xED,
	  0xD2, 0x04, 0x23, 0x1E, 0x37, 0x71, 0x0B, 0x9B,
	  0x05, 0x21, 0xCA, 0x44, 0xAB, 0x62, 0x04, 0x23,
	  0x00, 0xF3, 0xD0, 0x06, 0x35, 0xB5, 0xAC, 0x5F,
	  0x07, 0x04, 0x5A, 0x04, 0xFD, 0xF3, 0xD0, 0xF6,
	  0xF7, 0x77, 0xDE, 0x78, 0xFC, 0xCD, 0xEE, 0x2E,
	  0x04, 0x29, 0x92, 0x27, 0x0F, 0x91, 0x91, 0xED,
	  0x17, 0x10, 0xD4, 0x0A, 0xE4, 0x04, 0x1F, 0xC6,
	  0x27, 0x08, 0xE8, 0x97, 0xB3, 0x8F, 0xC5, 0xB3,
	  0x46, 0x90, 0x04, 0x95, 0xE8, 0x1C, 0x3C, 0xF5,
	  0x6D, 0x33, 0xA1, 0xE9, 0x74, 0x0A, 0xF8, 0x04,
	  0x34, 0x4B, 0x39, 0x6E, 0xD2, 0xF7, 0xDC, 0xFA,
	  0x69, 0x01, 0xFF, 0x0A, 0x04, 0xA0, 0x2D, 0x32,
	  0x6E, 0xCD, 0xDB, 0xC8, 0x39, 0x59, 0xD2, 0x88,
	  0x4C, 0x04, 0xAD, 0xF1, 0x32, 0x2F, 0xEA, 0xD3,
	  0x4E, 0xD0, 0xE9, 0xA4, 0xC1, 0x14, 0x04, 0x42,
	  0xF3, 0x25, 0xAD, 0xE0, 0xE6, 0x97, 0xE0, 0x6E,
	  0x98, 0x3C, 0x32, 0x04, 0x47, 0x5F, 0x22, 0x9D,
	  0xF3, 0x9F, 0xAA, 0x25, 0x22, 0x61, 0x19, 0x04,
	  0x04, 0xB5, 0xF0, 0x23, 0xEE, 0xE3, 0x14, 0x4A,
	  0x5A, 0xA3, 0x02, 0xCA, 0xB0, 0x04, 0xB5, 0x17,
	  0x33, 0xC9, 0xD3, 0x67, 0x30, 0x15, 0x21, 0x12,
	  0x02, 0xD4, 0x04, 0x71, 0xD0, 0x40, 0x2D, 0xF4,
	  0xC6, 0xA4, 0x13, 0xB7, 0x39, 0xDE, 0xAC, 0x04,
	  0xB5, 0xCA, 0x23, 0xAF, 0xF7, 0x30, 0xE8, 0xE2,
	  0x8C, 0x57, 0x17, 0xDC, 0x04, 0x48, 0xC4, 0x2A,
	  0xFF, 0xB1, 0xC6, 0x73, 0x44, 0x50, 0x59, 0xAA,
	  0x04, 0x04, 0xB5, 0xCA, 0x33, 0xFE, 0x91, 0xD5,
	  0x82, 0x12, 0x20, 0x8E, 0xEA, 0x26, 0x04, 0xAB,
	  0xB1, 0x48, 0xFE, 0x80, 0x7F, 0x78, 0x93, 0x8E,
	  0x0F, 0x15, 0x94, 0x04, 0xD3, 0x10, 0x6A, 0x43,
	  0xCB, 0x41, 0x75, 0x02, 0x25, 0x32, 0x3D, 0x7C,
	  0x04, 0x3F, 0x45, 0x3B, 0xFB, 0xFB, 0x2E, 0xEA,
	  0x67, 0x8E, 0xB5, 0x59, 0x3A, 0x04, 0xED, 0x41,
	  0x80, 0x1F, 0xCF, 0x4B, 0x53, 0x89, 0x19, 0x43,
	  0x88, 0x40, 0x04, 0x57, 0xD7, 0xF3, 0x7F, 0xF8,
	  0x9A, 0x0F, 0x73, 0xA2, 0x62, 0x60, 0x0C, 0x04,
	  0x1D, 0x3C, 0xCC, 0xFC, 0xC8, 0x65, 0x8B, 0x4F,
	  0x59, 0xA5, 0x61, 0xBE, 0x04, 0xD4, 0x77, 0x40,
	  0x9F, 0xFB, 0xA3, 0x65, 0x4D, 0xF6, 0xEE, 0x4F,
	  0x1C, 0x04, 0xAE, 0xBA, 0x43, 0x0F, 0xE9, 0xEF,
	  0x97, 0xBD, 0x1A, 0x37, 0xA4, 0x78, 0x04, 0xB5,
	  0x60, 0x3E, 0xAE, 0xC0, 0xAF, 0x97, 0x32, 0xB9,
	  0xE0, 0x41, 0x7A, 0x04, 0xB5, 0x10, 0x3A, 0xAE,
	  0xE2, 0x9D, 0xD0, 0xD7, 0x83, 0x19, 0x8E, 0x40,
	  0x04, 0xB5, 0xF0, 0x3B, 0xAC, 0xAE, 0xDF, 0x78,
	  0x0C, 0x79, 0xE6, 0x5B, 0x62, 0x04, 0xE7, 0x33,
	  0x38, 0xAC, 0xB4, 0xBD, 0x97, 0xD2, 0xAC, 0x52,
	  0xA2, 0xA2, 0x04, 0xD9, 0x73, 0x36, 0xAD, 0xF1,
	  0x56, 0x98, 0xAC, 0x92, 0xA2, 0x46, 0x68, 0x04,
	  0x8E, 0xC6, 0x35, 0xAD, 0xE4, 0x9C, 0xE7, 0xB4,
	  0x58, 0x50, 0xF5, 0xA2, 0x04, 0xD9, 0x73, 0x36,
	  0xAE, 0xE2, 0x94, 0xE4, 0xEE, 0xB6, 0xC5, 0x58,
	  0x9C, 0x04, 0xD9, 0x42, 0x36, 0xAB, 0xE3, 0x94,
	  0x6A, 0xC2, 0xC8, 0x2B, 0x20, 0x9C, 0x04, 0xB5,
	  0xF0, 0x36, 0x5D, 0xED, 0xE2, 0x10, 0x3B, 0x28,
	  0x82, 0x04, 0xE2, 0x04, 0xB5, 0x34, 0x32, 0xDD,
	  0x92, 0xD4, 0x24, 0x9C, 0x25, 0x61, 0xF5, 0xB8,
	  0x04, 0xD9, 0x10, 0x43, 0xFD, 0x9D, 0x88, 0xD9,
	  0x87, 0x8F, 0x64, 0xAD, 0x9E, 0x04, 0x3C, 0xEB,
	  0xFC, 0x2F, 0x3E, 0xB4, 0x29, 0xC7, 0x2C, 0x1A,
	  0x78, 0x9E, 0x04, 0x68, 0xF3, 0x46, 0x4E, 0xF7,
	  0x14, 0x5C, 0x1A, 0x0E, 0xBF, 0xB1, 0x4E, 0x04,
	  0x55, 0x11, 0x9F, 0xCF, 0x82, 0x0E, 0xE5, 0x0A,
	  0x40, 0x16, 0x63, 0x26, 0x04, 0xD4, 0x1F, 0x38,
	  0xBF, 0xF5, 0xE2, 0x22, 0x42, 0xC2, 0x8F, 0xE0,
	  0x64, 0x04, 0x42, 0x1D, 0x2E, 0x6C, 0xBE, 0xE1,
	  0xD9, 0xCA, 0xCC, 0x0A, 0x47, 0xE4, 0x04, 0x95,
	  0xC1, 0x2E, 0x9F, 0xE3, 0xF3, 0x27, 0xDB, 0xDB,
	  0x9F, 0x51, 0xA4, 0x04, 0x54, 0x27, 0x32, 0xBD,
	  0xEE, 0x0A, 0xA8, 0x5C, 0x0C, 0x04, 0xEB, 0x50,
	  0x04, 0x1E, 0xC1, 0x29, 0xBF, 0xE0, 0xDB, 0xD6,
	  0xB3, 0xFC, 0x1C, 0xC1, 0x5A, 0x04, 0xD9, 0x28,
	  0x32, 0xFE, 0x35, 0x1B, 0xC0, 0xFB, 0xA4, 0x91,
	  0xC7, 0x98, 0x04, 0x1E, 0xC8, 0x30, 0xFF, 0xFF,
	  0xB7, 0x6E, 0x3C, 0xA1, 0xD6, 0x31, 0xAA, 0x04,
	  0xE7, 0x01, 0x36, 0xFD, 0x96, 0x90, 0x5D, 0x5B,
	  0xF3, 0xB0, 0x97, 0x8A, 0x04, 0x42, 0xDC, 0x48,
	  0x5F, 0xD5, 0xB7, 0x5A, 0xCD, 0x7D, 0x70, 0x43,
	  0x4E, 0x04, 0x42, 0xDC, 0x3F, 0xBE, 0xF8, 0xD0,
	  0xE8, 0x10, 0x27, 0x9E, 0xD2, 0x52, 0x04, 0x42,
	  0x0F, 0x46, 0xED, 0xF5, 0xC7, 0xB1, 0x85, 0xE4,
	  0x69, 0xB3, 0x68, 0x04, 0x8F, 0x61, 0x4E, 0xFF,
	  0xE5, 0x81, 0x61, 0xC8, 0x38, 0x13, 0x22, 0x42,
	  0x04, 0xD3, 0xFC, 0x5E, 0x7B, 0xFD, 0xAA, 0x7E,
	  0xBC, 0x86, 0x61, 0x1C, 0xFC, 0x04, 0x95, 0x63,
	  0x5F, 0xCB, 0x90, 0xDF, 0x34, 0x88, 0xB6, 0x24,
	  0xA6, 0x20, 0x04, 0xB5, 0xF9, 0x6B, 0xFD, 0x9C,
	  0x63, 0x46, 0x20, 0x3A, 0x41, 0x24, 0xAC, 0x04,
	  0xD4, 0xA7, 0x6F, 0xCF, 0x97, 0xDC, 0x71, 0xE1,
	  0xAB, 0xB1, 0x3A, 0x9C, 0x04, 0x95, 0x40, 0x77,
	  0xF8, 0x88, 0x22, 0xB3, 0x8F, 0x94, 0xA8, 0xC6,
	  0x04, 0x04, 0xAB, 0x38, 0x67, 0xF9, 0x3B, 0x86,
	  0x35, 0x90, 0xC8, 0x14, 0x9F, 0x60, 0x04, 0xB5,
	  0x9C, 0x6C, 0xE4, 0x7B, 0x4C, 0xD4, 0x7C, 0x2C,
	  0x8E, 0x0D, 0x50, 0x04, 0x95, 0x08, 0x6B, 0xC3,
	  0x16, 0xEA, 0x45, 0xBB, 0xC5, 0xCD, 0x71, 0x70,
	  0x04, 0x95, 0xFC, 0xF0, 0xF3, 0x0B, 0x3A, 0x74,
	  0x39, 0x6C, 0x64, 0x9D, 0xCC, 0x04, 0xE7, 0x26,
	  0xF3, 0x03, 0x0E, 0xF7, 0x3A, 0x25, 0xD1, 0x09,
	  0x2E, 0x54, 0x04, 0x36, 0x3C, 0x34, 0x35, 0xFF,
	  0xA0, 0xBA, 0xE1, 0x41, 0x7A, 0x4C, 0x14, 0x04,
	  0x3B, 0x42, 0x04, 0x2F, 0x8B, 0x63, 0x64, 0x0E,
	  0x8B, 0x36, 0xBB, 0x1A, 0x04, 0xD4, 0xEC, 0x40,
	  0xCF, 0xEA, 0x65, 0xAE, 0xB8, 0x44, 0xF4, 0x6B,
	  0xEE, 0x04, 0xD3, 0x1D, 0x6A, 0xDF, 0x93, 0x67,
	  0xAA, 0x8E, 0x60, 0xC8, 0x82, 0x00, 0x04, 0xD3,
	  0xC7, 0x6A, 0xAB, 0x9A, 0xFC, 0x53, 0x24, 0xE2,
	  0x86, 0x8A, 0x92, 0x04, 0xF3, 0xC7, 0x6E, 0x9B,
	  0xC3, 0xA7, 0x2A, 0xE7, 0xDC, 0x7B, 0x84, 0x4A,
	  0x04, 0xB5, 0xF1, 0x6E, 0xBB, 0x32, 0xFA, 0x24,
	  0xA0, 0xED, 0x41, 0x6A, 0x62, 0x04, 0xF3, 0x4B,
	  0x75, 0xBB, 0x9E, 0xC0, 0x69, 0x5B, 0x54, 0x80,
	  0x6F, 0x54, 0x04, 0xF3, 0x09, 0x77, 0xFC, 0x73,
	  0x1E, 0xBB, 0x11, 0x75, 0x31, 0xBC, 0xE8, 0x04,
	  0xF3, 0x37, 0x77, 0xF0, 0x0B, 0x07, 0x55, 0xD9,
	  0xF8, 0x09, 0x2E, 0x4E, 0x04, 0xFE, 0x3C, 0x3F,
	  0xBE, 0x0D, 0x2C, 0x33, 0x91, 0x87, 0x95, 0x14,
	  0x44, 0x04, 0x34, 0x56, 0xAE, 0xF0, 0x2D, 0x19,
	  0xE3, 0xAD, 0xFC, 0x75, 0x36, 0x4E, 0x04, 0xFF,
	  0x18, 0x93, 0xC0, 0x17, 0x13, 0xC5, 0x9A, 0xD1,
	  0x47, 0xE1, 0x1A, 0x04, 0x58, 0xEA, 0x8F, 0xF0,
	  0x07, 0x06, 0x85, 0xFF, 0xE1, 0x04, 0xD2, 0xD2,
	  00
};
size_t audiostream_len = sizeof(audiostream)/sizeof(audiostream[0]);

s32 audio_handle;
s32 bufsize;
void *streambuf;
s32 currentpos = 0;

bool
irq_lowlevel(adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel, adl_irqEventData_t *Data)
{
	TRACE (( 1, "irq_lowlevel"));

	if (currentpos >= audiostream_len)
	{
		return TRUE;  /* Notify high-level IRQ */
	}
	wm_memcpy(streambuf, (const u8 *)&audiostream[ currentpos ], bufsize);
	currentpos += bufsize;

	*( (adl_audioStream_t *)Data->SourceData)->BufferReady = TRUE;

	return FALSE;      /* Don't notify high level IRQ */
}

bool
irq_highlevel(adl_irqID_e Source, adl_irqNotificationLevel_e NotificationLevel, adl_irqEventData_t *Data)
{
	TRACE(( 1, "irq_highlevel" ));
	adl_audioStop(audio_handle);
	return FALSE;      /* Return value is ignored in high-level IRQ */
}

// Audio Event Handler
void AudioEventHandler( s32 Handle, adl_audioEvents_e Event )
{
	TRACE (( 3, "AudioEventHandler: Event [%d]", Event ));
	return;
}

// Task startup delay timer handler
void TaskStartupTimerHandler( u8 Id, void *Context)
{
	  s32 irq_handle;
	  s32 irq_high_handle;
	  s32 ret;

	  // create handle for all audio events
	  audio_handle = adl_audioSubscribe ( ADL_AUDIO_SPEAKER, AudioEventHandler, ADL_AUDIO_RESOURCE_OPTION_FORBID_PREEMPTION );
	  TRACE (( 2, "audio_handle: %d", audio_handle ));
	  // NOTE: handle negative values here - denote errors

	  irq_handle = adl_irqSubscribe(irq_lowlevel, ADL_IRQ_NOTIFY_LOW_LEVEL,
			  	  	  	  	ADL_IRQ_PRIORITY_LOW_LEVEL,      /* Priority level */
			  	  	  	ADL_IRQ_OPTION_AUTO_READ);      /* Required option */
	  TRACE (( 2, "irq_handle: %d", irq_handle ));

	  irq_high_handle = adl_irqSubscribe(irq_highlevel, ADL_IRQ_NOTIFY_HIGH_LEVEL,
			  	  	  	  	  ADL_IRQ_PRIORITY_HIGH_LEVEL,      /* Priority level */
							0);      /* Options (ignored for low level IRQs) */
	  TRACE (( 2, "irq_high_handle: %d", irq_high_handle ));

	  adl_audioGetOption( audio_handle, ADL_AUDIO_AMR_BUFFER_SIZE, &bufsize);
	  TRACE (( 2, "audioGetOption: ADL_AUDIO_AMR_BUFFER_SIZE: [%d]", bufsize));

	  bufsize = audiostream_len;
	  TRACE (( 2, "bufsize: [%d]", bufsize));

	  // Set Mixed voice option
	  adl_audioSetOption (audio_handle, ADL_AUDIO_AMR_MIXED_VOICE, FALSE);
	  // Set Codec Rate
	  adl_audioSetOption (audio_handle, ADL_AUDIO_AMR_SPEECH_CODEC_RATE, ADL_AUDIO_AMR_RATE_4_75);
	  // Set Buffer Size
	  ret = adl_audioSetOption (audio_handle, ADL_AUDIO_AMR_BUFFER_SIZE, bufsize);
	  TRACE (( 2, "adl_audioSetOption:ADL_AUDIO_AMR_BUFFER_SIZE returns [%d]", ret ));
	  // Memory allocation
	  streambuf = adl_memGet(bufsize);
	  ret = adl_audioStreamPlay(audio_handle, ADL_AUDIO_AMR, irq_handle, irq_high_handle, streambuf);
	  TRACE (( 2, "audioStreamPlay: returns [%d]", ret ));

	  return;
}


void
main_task (void)
{

  TRACE (( 1, "main_task: Start:" ));

  // wait 5 seconds before starting rest of task (in case we need to issue AT+WOPEN=0 !!!!
  adl_tmrSubscribe ( FALSE, 50, ADL_TMR_TYPE_100MS, TaskStartupTimerHandler );

}

ciao, Dave

My apologies, they are mostly problems due to copy&paste. My program is more complex, but I mimized it to show just the problem with AMR exception.

I don’t agree with you just on the last point: C standard guarantees that static variables are initialized to zero values.

Ok, the first one that receive the answer from SiWi, will post it in the forum.