📄 player_lib.c
字号:
* *
* 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 + -