コード例 #1
0
bool buff_player_dacs_output(void *sample_buffer, size_t sample_length)
{
  if (!buff_player_pcm_buf_fifo)
    return false;

  if (!sample_length)
    return (!buff_player_is_pcm_buf_fifo_full());

  if (audio_mixer_dacs_output_direct(NULL, 0))
    audio_mixer_dacs_output_direct(sample_buffer, sample_length);

  return buff_player_put_pcm_buf(sample_buffer, sample_length);
}
コード例 #2
0
//!
//! @brief This callback function is called when the DAC interrupt has sent
//! the buffer 'n-1' and switches to buffer 'n'. The aim of this function is thus to prepare
//! the buffer 'n+1'; so that there is always a pending buffer for the interrupt.
//!
void dac_sample_sent_cb( void )
{
   uint16_t fifo_used_cnt=usb_stream_fifo_get_used_room();

   if( fifo_used_cnt==0 )
   {
      // Unexpected interrupt.
      usb_stream_context->synchronized = false;
      usb_stream_context->status = USB_STREAM_ERROR_NOT_SYNCHRONIZED;
      return;
   }

   // Previous buffer has been sent by the DAC driver.
   usb_stream_fifo_pull();
   fifo_used_cnt--;

   if( fifo_used_cnt!=0 )
   {
      void* buffer;
      uint16_t   size;

      usb_stream_fifo_get(&buffer, &size);
      audio_mixer_dacs_output_direct(buffer, size/(usb_stream_context->channel_count*usb_stream_context->bits_per_sample/8));
   }
   else
   {
      usb_stream_context->synchronized = false;
      usb_stream_context->status = USB_STREAM_ERROR_NOT_SYNCHRONIZED;
   }
}
コード例 #3
0
void buff_player_dacs_end_of_pcm_buf(void)
{
  buff_player_pcm_buf_t pcm_buf;

  if (!buff_player_pcm_buf_fifo)
    return;

  buff_player_remove_used_pcm_buf();

  if (!buff_player_peek_reload_pcm_buf(&pcm_buf))
    return;

  audio_mixer_dacs_output_direct(pcm_buf.sample_buffer, pcm_buf.sample_length);
}
コード例 #4
0
static bool usb_stream_process(void)
{
    buffer_t *input_buffer;
#if (defined __GNUC__)
    dsp16_t * volatile dsp16_output_buffer;
#else
    dsp16_t * dsp16_output_buffer;
#endif
    int i, channel, size = 0;

    // If no buffer is ready, then set under flow marker
    if (usb_stream_context->current_full_buffer == -1)
        return false;

    // If the audio DAC is not ready to receive more data, then return
    if (!audio_mixer_dacs_output_direct(NULL, 0))
        return false;

    // Select the current input buffer and make sure it is valid
    input_buffer = usb_stream_context->input_buffers[usb_stream_context->current_full_buffer];

    // Make sure this buffer is not already in the process of resampling
    if (input_buffer->buffer_state != BUFFER_STATE_FULL)
        return false;

    // Mark this buffer as a "resampling" buffer
    input_buffer->buffer_state = BUFFER_STATE_RESAMPLING;

    // Select the current output buffer
    dsp16_output_buffer = (dsp16_t *) usb_stream_context->output_buffers[usb_stream_context->current_output_buffer];

    for (channel=0; channel<usb_stream_context->nb_channels; channel++)
    {
        // Interpolates the current channel buffer
        dsp16_resampling_compute(usb_stream_context->ctx->resampling,
                                 usb_stream_context->output_temp_buffer,
                                 input_buffer->buffer[channel],
                                 channel);
        size = dsp16_resampling_get_output_current_buffer_size(usb_stream_context->ctx->resampling);
        // Fill the array with audio samples and mix the channels
        switch (usb_stream_context->nb_channels)
        {
        case 1:
            memcpy(dsp16_output_buffer, usb_stream_context->output_temp_buffer, usb_stream_context->input_buffer_size);
            break;
        case 2:
            for (i=0; i<size; i++)
                dsp16_output_buffer[i*2] = ((dsp16_t *) usb_stream_context->output_temp_buffer)[i];
            break;
        default:
            for (i=0; i<size; i++)
                dsp16_output_buffer[i*usb_stream_context->nb_channels] = ((dsp16_t *) usb_stream_context->output_temp_buffer)[i];
        }
        // change channel
        dsp16_output_buffer++;
    }

    // Re-selects the current output buffer
    dsp16_output_buffer = (dsp16_t *) usb_stream_context->output_buffers[usb_stream_context->current_output_buffer];

    // Scale the output buffer if the scaling is set
    if (usb_stream_context->ctx->gain)
        dsp16_vect_realdiv(dsp16_output_buffer, dsp16_output_buffer, size * usb_stream_context->nb_channels, usb_stream_context->ctx->gain);

    // Send the buffer to the output channel
    audio_mixer_dacs_output_direct(dsp16_output_buffer, size);

    // Set the current input buffer as an empty buffer
    input_buffer->buffer_state = BUFFER_STATE_EMPTY;

    // Update the current output buffer index
    usb_stream_context->current_output_buffer = (usb_stream_context->current_output_buffer+1)%AUDIO_STREAM_NB_OUTPUT_BUFFERS;

    // Update the current full buffer pointer
    i = (usb_stream_context->current_full_buffer+1)%AUDIO_STREAM_NB_INPUT_BUFFERS;
    input_buffer = usb_stream_context->input_buffers[i];
    if (input_buffer->buffer_state != BUFFER_STATE_FULL)
        i = -1;
    usb_stream_context->current_full_buffer = i;

    return true;
}
コード例 #5
0
//!
//! @brief This function takes the stream coming from the selected USB pipe and sends
//! it to the DAC driver. Moreover, it ensures that both input and output stream
//! keep synchronized by adding or deleting samples.
//!
//! @param side          USB_STREAM_HOST for USB host, USB_STREAM_DEVICE for device.
//! @param pipe_in       Number of the addressed pipe/endpoint
//! @param pFifoCount    (return parameter) NULL or pointer to the number of used buffers at this time
//!
//! @return              status: (USB_STREAM_STATUS_OK, USB_STREAM_STATUS_NOT_SYNCHRONIZED,
//!                      USB_STREAM_STATUS_SPEED_UP, USB_STREAM_STATUS_SLOW_DOWN, USB_STREAM_STATUS_BUFFER_OVERFLOW)
//!
int usb_stream_input(usb_stream_side_t side, uint8_t pipe_in, uint32_t* pFifoCount)
{
   uint16_t      fifo_used_cnt;
   uint16_t      byte_count=0;
   uint32_t      i;
   UnionPtr pswap;
   UnionPtr buffer;

   // We comes here since we have received something. Let's increase the internal
   // activity counter.
   usb_stream_cnt++;

   fifo_used_cnt=usb_stream_fifo_get_used_room();
   if (pFifoCount)
      *pFifoCount = fifo_used_cnt;

   // usb_stream_fifo_get_free_room()
   if( USB_STREAM_BUFFER_NUMBER-fifo_used_cnt==0 )
   {  // Fatal error: even with the synchro mechanism acting, we are in a case in which the
      // buffers are full.
      usb_stream_context->synchronized = false;
      usb_stream_context->status = USB_STREAM_ERROR_NOT_SYNCHRONIZED;
      return usb_stream_context->status;
   }

   pswap.s8ptr  =
   buffer.s8ptr = usb_stream_fifo_get_buffer(usb_stream_context->wr_id);

#if USB_HOST_FEATURE == true
   if( side==USB_STREAM_HOST )
   {
      byte_count=Host_byte_count(pipe_in);
   }
#endif
#if USB_DEVICE_FEATURE == true
   if( side==USB_STREAM_DEVICE )
   {
      byte_count=Usb_byte_count(pipe_in);
   }
#endif
  if( byte_count==0 )
  {
     if( cpu_is_timeout(&broken_stream_timer) ) {
        usb_stream_context->status = USB_STREAM_ERROR_BROKEN_STREAM;
     } else {
        usb_stream_context->status = USB_STREAM_ERROR_NO_DATA;
     }
     return usb_stream_context->status;
  }
  else
  {
    // reset time out detection
    cpu_set_timeout(cpu_ms_2_cy(BROKEN_STREAM_TIMER, FCPU_HZ), &broken_stream_timer);
  }

#if USB_HOST_FEATURE == true
   if( side==USB_STREAM_HOST )
   {
      Host_reset_pipe_fifo_access(pipe_in);
      host_read_p_rxpacket(pipe_in, (void*)buffer.s8ptr, byte_count, NULL);
	 }
#endif
#if USB_DEVICE_FEATURE == true
   if( side==USB_STREAM_DEVICE )
	 {
      Usb_reset_endpoint_fifo_access(pipe_in);
      usb_read_ep_rxpacket(pipe_in, (void*)buffer.s8ptr, byte_count, NULL);
	}
#endif

   usb_stream_context->status = USB_STREAM_ERROR_NONE;

   if( byte_count > USB_STREAM_REAL_BUFFER_SIZE )
   {
      byte_count = USB_STREAM_REAL_BUFFER_SIZE;
      usb_stream_context->status = USB_STREAM_ERROR_OVERFLOW;
   }

   // Swap samples since they are coming from the USB world.
   if( usb_stream_context->bits_per_sample==16 )
      for( i=0 ; i<byte_count/(16/8) ; i++ )
         pswap.s16ptr[i] = swap16(pswap.s16ptr[i]);

   else if( usb_stream_context->bits_per_sample==32 )
      for( i=0 ; i<byte_count/(32/8) ; i++ )
         pswap.s32ptr[i] = swap32(pswap.s32ptr[i]);

   //for( i=0 ; i<byte_count/2 ; i++ )
   //   printf("0x%04hx ", pswap[i]);
   //printf("\r\n");

   usb_stream_fifo_push(byte_count);
   fifo_used_cnt++;

   if( !usb_stream_context->synchronized )
   {
      usb_stream_context->status = USB_STREAM_ERROR_NOT_SYNCHRONIZED;

      if( fifo_used_cnt>=(USB_STREAM_BUFFER_NUMBER/2) )
      {  // We have enough buffers to start the playback.
         void* buffer;
         uint16_t   size;

         // CS2200
         cs2200_freq_clk_out(_32_BITS_RATIO(usb_stream_resync_frequency, CS2200_FREF));
         usb_stream_resync_step = PPM(usb_stream_resync_frequency, USB_STREAM_RESYNC_PPM_STEPS);
         usb_stream_resync_freq_ofst = usb_stream_resync_frequency;
         usb_stream_resync_ppm_ofst = 0;
         usb_stream_resync_last_room = fifo_used_cnt;
#define TIMER_USB_RESYNC_CORRECTION  320
         cpu_set_timeout( cpu_ms_2_cy(TIMER_USB_RESYNC_CORRECTION, FCPU_HZ), &usb_resync_timer );

         usb_stream_context->synchronized=true;
         usb_stream_fifo_get(&buffer, &size);
         audio_mixer_dacs_output_direct(buffer, size/(usb_stream_context->channel_count*usb_stream_context->bits_per_sample/8));

         // Fill also the reload stage of the PDCA.
         usb_stream_fifo_pull();
         usb_stream_fifo_get(&buffer, &size);
         audio_mixer_dacs_output_direct(buffer, size/(usb_stream_context->channel_count*usb_stream_context->bits_per_sample/8));
      }
   }

   return usb_stream_context->status;
}