Example #1
0
void sound_play_sample(U8 *data, U32 length, U32 freq, int vol)
{
  if (data == (U8 *) 0 || length == 0) return;
  // Calculate the clock divisor based upon the recorded sample frequency */
  if (freq == 0) freq = DEFRATE;
  if (freq > MAXRATE) freq = MAXRATE;
  if (freq < MINRATE) freq = MINRATE;
  U32 cdiv = (OSC/(2*SAMPBITS) + freq/2)/freq;
  set_vol(vol);
  // Turn off ints while we update shared values
  sound_interrupt_disable();
  sound_mode = SOUND_MODE_PCM;
  sample.count = length;
  sample.ptr = data;
  sample.len = PDM_BUFFER_LENGTH;
  sample.clock_div = cdiv;
  // re-enable and wait for the current sample to complete
  sound_interrupt_enable(AT91C_SSC_TXBUFE);
  *AT91C_SSC_PTCR = AT91C_PDC_TXTEN;
}
Example #2
0
int sound_add_sample(U8 *data, U32 length, U32 freq, int vol)
{
  // Add a set of samples into the playback queue, if not currently
  // playing start the playback process.
  
  // If this is the first sample simply start to play it
  if (sound_mode != SOUND_MODE_PCM || sample.ptr != sample.sample_buf)
  {
    if (sample.sample_buf == NULL)
    {
      sample.sample_buf = system_allocate(SAMPLEBUFSZ);
      if (sample.sample_buf == NULL) return -1;
    }
    if (length > SAMPLEBUFSZ - 1) length = SAMPLEBUFSZ - 1;
    memcpy(sample.sample_buf, data, length);
    sound_play_sample(sample.sample_buf, length, freq, vol);
    return length;
  }
  // Otherwise add the data to the buffer
  // Turn off ints while we update shared values
  sound_interrupt_disable();
  // add the data
  U8 *sbuf = sample.ptr;
  U32 in = sample.in_index;
  U32 out = sample.out_index;
  int cnt = (int) ((out - in - 1) & (SAMPLEBUFSZ - 1));
  if (cnt > length) cnt = length;
  length = cnt;
  while (cnt-- > 0)
  {
    sbuf[in] = *data++;
    in = (in + 1) & (SAMPLEBUFSZ - 1);
  }
  sample.in_index = in;
  sample.count = (((in - out) & (SAMPLEBUFSZ - 1)) + SAMPPERBUF - 1)/SAMPPERBUF;
   
  // re-enable and wait for the current sample to complete
  sound_interrupt_enable(AT91C_SSC_ENDTX);
  *AT91C_SSC_PTCR = AT91C_PDC_TXTEN;
  return length;
}
Example #3
0
void sound_isr_C()
{
//U64 s = systick_get_ns();
    if (sample.count > 0)
    {
      // refill the buffer, and adjust any clocks
      *AT91C_SSC_CMR = sample.clock_div;
      sound_enable();
      if (*AT91C_SSC_TCR == 0)
      {
        if (sound_mode == SOUND_MODE_PCM)
        {
          sound_fill_sample_buffer();
          *AT91C_SSC_TPR = (unsigned int)sample.buf[sample.buf_id];
        }
        else
          *AT91C_SSC_TPR = (unsigned int)sample.ptr;
        *AT91C_SSC_TCR = sample.len;
        sample.count--;
      }
      if (sound_mode == SOUND_MODE_PCM)
      {
        sound_fill_sample_buffer();
        *AT91C_SSC_TNPR = (unsigned int)sample.buf[sample.buf_id];
      }
      else
        *AT91C_SSC_TNPR = (unsigned int)sample.ptr;
      *AT91C_SSC_TNCR = sample.len;
      sample.count--;
      // If this is the last sample wait for it to complete, otherwise wait
      // to switch buffers
      sound_interrupt_enable(AT91C_SSC_ENDTX);
    }
    else
    {
      sound_disable();
      sound_interrupt_disable();
    }
//ttime += (systick_get_ns() - s);
}
Example #4
0
void sound_freq(U32 freq, U32 ms, int vol)
{
  // Set things up ready to go, note we avoid using anything that may
  // be used by the interupt routine because ints may still be enabled
  // at this point
  int len;
  // we use longer samples for lower frequencies
  if (freq > 1000)
    len = 16;
  else if (freq < 500)
    len = 64;
  else
    len = 32;
  sound_mode = SOUND_MODE_TONE;
  // Update the volume lookup table if we need to
  set_vol(vol);
  int buf = sample.buf_id^1;
  create_tone(sine, sizeof(sine), sample.buf[buf], len); 
  // The note gneration takes approx 1ms, to ensure that we do not get gaps
  // when playing a series of tones we extend the requested period to cover
  // this 1ms cost.
  ms += TONE_OVERHEAD;
  // Turn of ints while we update shared values
  sound_interrupt_disable();
  /* Genrate the pdm wave of the correct amplitude */
  sample.clock_div = (OSC/(len*32*2) + freq/2)/freq;
  // Calculate actual frequency and use this for length calc
  freq = (OSC/(2*sample.clock_div))/(len*32);
  if (ms <= TONE_OVERHEAD)
    sample.count = 0;
  else
    sample.count = (freq*ms + 1000-1)/1000;
  sample.len = len;
  sample.ptr = (U8 *)sample.buf[buf];
  sample.buf_id = buf;
  *AT91C_SSC_PTCR = AT91C_PDC_TXTEN;
  sound_mode = SOUND_MODE_TONE;
  sample.in_index = sample.out_index;
  sound_interrupt_enable(AT91C_SSC_TXBUFE);
}