⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 player_lib.c

📁 MP3 Cyclone的source code 利用FPGGA實現MP3的功能
💻 C
📖 第 1 页 / 共 3 页
字号:
 *                                                                     *
 * Input:   none                                                       *
 * Output:  none                                                       * 
 * Returns: Value of the button PIO                                    *
 **********************************************************************/

int NiosIIMP3_ReadButtons( void )
{
  int button_data;
  
  button_data = IORD_ALTERA_AVALON_PIO_DATA( BUTTON_PIO_BASE );
  button_data = ( ( ~button_data ) & 0xF );
  
  return button_data;
}

/***********************************************************************
 * Function: NiosIIMP3_PlayAudio                                       *
 *                                                                     *
 * Purpose: Sets the sampling rate for the PWM output, then takes a    *
 *          buffer of pcm samples and hands them to the PWM playback   *
 *          function.  Since the PWM buffer might be full, the PWM     *
 *          playback function is perpetually called until it returns 0 *
 *          meaning it accepted the samples.                           *
 *                                                                     *
 * Input:   Pointer to the MP3 file structure. (passed in as a void*)  *
 *          Pointer to the decoder's header structure (not used)       *
 *          Pointer to the decoder's PCM output sample buffers         *
 * Output:  Samples are sent to the play audio routine                 * 
 * Returns: Return code indicating whether to restart playback         *
 **********************************************************************/

int NiosIIMP3_PlayAudio( struct mad_pcm *pcm )
{
  alt_u32 leds;
  alt_u32 ret_code = 1;
  
  /* This little routine shows the PWM FIFO level on 8 LEDs */
  if( SHOW_FIFO_FULLNESS )
  {
    leds = IORD_16DIRECT( AUDIO_PWM_BASE, PWM_FIFO_USED_OFFSET );;
    leds = ( ( leds * 100 ) / FILE_BUFFER_SIZE );
    leds = ( 1 << ( leds / 14 ) );
    IOWR( LED_PIO_BASE, 0, leds );
  }
  
  PWM_SetSamplingRate( pcm->samplerate, AUDIO_PWM_BASE );
  /* 
   * Keep calling the PWM play routine until it returns 0.  If it returns -1, 
   * that means it rejected the samples because the FIFO was full.  Since 
   * it's constantly playing audio, the FIFO will empty eventually
   */
  while( ret_code )
  {
    ret_code = PWM_PlaySamples( pcm->samples[0],
                                pcm->samples[1],
                                pcm->length,
                                pcm->samplerate,
                                AUDIO_PWM_FIFO_DEPTH, 
                                AUDIO_PWM_BASE );
  }
  return( ret_code );
}

/***********************************************************************
 * Function: NiosIIMP3_MeasurePerformance                              *
 *                                                                     *
 * Purpose: Periodically calculates and displays how many samples are  *
 *          being generated per second by the decoder.  This is also   *
 *          compared with the intended audio output sample rate and    *
 *          displays the decode performance as a percentage of the     *
 *          required output rate.                                      *
 *                                                                     *
 * Input:   Pointer to the decoder's PCM output sample buffers         *
 * Output:  Character output to STDOUT indicating performance metrics  * 
 * Returns: 0                                                          *
 **********************************************************************/

int NiosIIMP3_MeasurePerformance( struct mad_pcm *pcm )
{
  static alt_u32 prev_num_samples = 0;
  static alt_u32 total_num_samples = 0;
  static alt_u32 next_measurement_time = 0;
  alt_u32 current_time, time_in_sec, samp_per_sec, percent_of_output;
  
  total_num_samples += pcm->length;
  
  current_time = alt_nticks();
  if( current_time >= next_measurement_time )
  {
    time_in_sec = current_time / alt_ticks_per_second();
    samp_per_sec = ( ( total_num_samples - prev_num_samples ) / 
                       SECS_BETWEEN_MEAS );
    percent_of_output = ( ( samp_per_sec * 100 ) / pcm->samplerate );
    next_measurement_time += ( alt_ticks_per_second() * SECS_BETWEEN_MEAS );
    prev_num_samples = total_num_samples;
    
    printf("Sec: %3d  S/S: %6d   %3d%%\n", 
      ( int )time_in_sec, ( int )samp_per_sec, ( int )percent_of_output );
  }   
  
  return 0;
}

/***********************************************************************
 * Function: NiosIIMP3_FillFileBuffer                                  *
 *                                                                     *
 * Purpose: Refills the file buffer from the file starting at the file *
 *          position requested, calling on the FAT filesystem to read  *
 *          data out of the file into the file buffer.                 *
 *          Since there's usually some data leftovers in the file      *
 *          buffer that we havent yet processed and want to keep, we   *
 *          move that to the front before refilling                    *
 *                                                                     *
 * Input:   Pointer to the MP3 file structure.                         *
 *          Position in the file we want at the front of the buffer    *
 * Output:  A refilled file buffer that starts with a valid frame      * 
 * Returns: void                                                       *
 **********************************************************************/

void NiosIIMP3_FillFileBuffer( nios_mp3_file_struct *mp3_files, int file_pos_needed )
{
  
  alt_u32 copy_size;     /* amount we'll try to copy into the file buffer */
  alt_u32 unproc_data_size; /* amount of unprocessed data left in the file buffer */

  /* 
   * If the file offset we're looking for is beyond what we've read into 
   * the buffer so far, we need to spool through the file until we get there
   */  
  while( file_pos_needed > mp3_files->file_position )
  {
    /* Fill the whole file buffer from FAT filesystem */
    read_file( mp3_files->fat_file_handle, 
             ( mp3_files->file_buffer ),
               FILE_BUFFER_SIZE );
    mp3_files->file_position += FILE_BUFFER_SIZE;
  }
  
  /*
   * This moves all unprocessed data at the end of the buffer to the beginning 
   * of the buffer to make room for new data
   */
  unproc_data_size = mp3_files->file_position - file_pos_needed;
  memmove( mp3_files->file_buffer,
           mp3_files->file_buffer + mp3_files->file_buffer_size - unproc_data_size,
           unproc_data_size );

  /* Trim copy_size if it points past the end of the file. */
  copy_size = FILE_BUFFER_SIZE - unproc_data_size;
  if( mp3_files->file_position + copy_size > mp3_files->file_length )
  {
    copy_size = mp3_files->file_length - mp3_files->file_position;    
  }
 
  /* Copy data from the FAT filesystem into the file buffer */
  read_file( mp3_files->fat_file_handle, 
             mp3_files->file_buffer + unproc_data_size, 
             copy_size );
  
  /* Calculate new file and buffer levels */
  mp3_files->file_buffer_size = copy_size + unproc_data_size;
  mp3_files->file_position += copy_size;

}

/***********************************************************************
 * Function: NiosIIMP3_NextFile                                        *
 *                                                                     *
 * Purpose: Increments file index to next file (with wrap-around)      *
 *                                                                     *
 * Input:   Pointer to the MP3 file structure.                         *
 * Output:  Incremented file number                                    * 
 * Returns: void                                                       *
 **********************************************************************/

inline void NiosIIMP3_NextFile( nios_mp3_file_struct *mp3_files )
{
  if( mp3_files->file_number >= mp3_files->file_count - 1 )
    mp3_files->file_number = 0;
  else 
    mp3_files->file_number++;
}

/***********************************************************************
 * Function: NiosIIMP3_PrevFile                                        *
 *                                                                     *
 * Purpose: Decrements file index to prev file (with wrap-around)      *
 *                                                                     *
 * Input:   Pointer to the MP3 file structure.                         *
 * Output:  Decremented file number                                    * 
 * Returns: void                                                       *
 **********************************************************************/

inline void NiosIIMP3_PrevFile( nios_mp3_file_struct *mp3_files )
{
  if( mp3_files->file_number <= 0  )
    mp3_files->file_number = mp3_files->file_count - 1;
  else 
    mp3_files->file_number--;
}

/***********************************************************************
 * Function: NiosIIMP3_ShowSpinner                                     *
 *                                                                     *
 * Purpose: Spins the 7-seg display like a clock                       *
 *                                                                     *
 * Input:   Flag indicating whether the spinner is active              *
 * Output:  Writes new output to 7-seg display                         * 
 * Returns: void                                                       *
 **********************************************************************/

void NiosIIMP3_ShowSpinner( int active )
{
  static long InnerSpinFrames[6] =
    { 0x0001,0x0004,0x1000,0x0100,0x2000,0x0002 };
  static long OuterSpinFrames[8] =
    { 0x0040,0x0020,0x0010,0x0008, 0x0800,0x0400,0x0200,0x4000 };
  
  alt_u32 display_value;
  static alt_u32 phase = 0;

  /* Spin seven seg only if we're told it's active */
  if( active == 0 )
  {
    IOWR_ALTERA_AVALON_PIO_DATA( SEVEN_SEG_PIO_BASE, 0xffff );
    phase = 0;
  }
  else
  {
    display_value =  InnerSpinFrames[ phase % 6 ];
    display_value |= OuterSpinFrames[ ( phase / 6 ) % 8 ];
    phase++;
    
    IOWR_ALTERA_AVALON_PIO_DATA( SEVEN_SEG_PIO_BASE, ~display_value );    
  }
}

/***********************************************************************
 * Function: NiosIIMP3_FileFinished                                    *
 *                                                                     *
 * Purpose: Checks if the current file is finished playing             *
 *                                                                     *
 * Input:   Pointer to the MP3 file structure.                         *
 * Output:  none                                                       * 
 * Returns: 0 = not finished, 1 = finished                             *
 **********************************************************************/

inline int NiosIIMP3_FileFinished( nios_mp3_file_struct* mp3_files )
{
  return( mp3_files->file_position >= mp3_files->file_length );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -