/*! @file audio.hcc * * @section generic Audio init and main loop * * @section project Project information. * Project Graphic Equalizer\n * @author O.M. Schinagl * @date 20041011 * @version 0.1 * * @section copyright Copyright * Copyright ©2004 Koninklijke Philips Electronics N.V. All rights reserved * * @section history Change history * 20041011: \n Initial version * ********************************************************************/ #include #include "pal_master.hch" #include "configuration.hch" #include "smartmedia_shared.hch" #include "display_shared.hch" #if USE_RUNFFT #include "audio.hch" #include "fft.hch" #include "smartmedia.hch" #endif #if HAVE_DEBUG #include "debug.hch" #endif /* * Forward declarations */ static macro expr ClockRate = PAL_ACTUAL_CLOCK_RATE; #if HARDWARE_MULTIPLY //input buffer ram signed 18 audio_buffer_in[256] with { block = "BlockRAM"}; //output buffer ram signed 18 audio_buffer_out[128] with { block = "BlockRAM"}; #else //input buffer ram signed 16 audio_buffer_in[256] with { block = "BlockRAM"}; //output buffer ram signed 16 audio_buffer_out[128] with { block = "BlockRAM"}; #endif //EQ settings for the FFT ram unsigned 4 EQ_info[128] with { block = "BlockRAM"}; //EQ settings received from the display chan 1 event_notification; #if HARDWARE_MULTIPLY signed 18 *audioptr_in1,*audioptr_in2,*audioptr_in3,*audioptr_in4; signed 18 *audioptr_out1,*audioptr_out2; unsigned 6 *displayptr1,*displayptr2,*displayptr3,*displayptr4; #else signed 16 *audioptr_in1,*audioptr_in2,*audioptr_in3,*audioptr_in4; signed 16 *audioptr_out1,*audioptr_out2; unsigned 6 *displayptr1,*displayptr2,*displayptr3,*displayptr4; #endif unsigned 1 FFT_Sync; signed Output_sample; /*! \fn macro proc audio_init(gain_level, input_source, sample_rate, AUDIOIN, AUDIOOUT) * * \brief Set some inital values to the audio hardware. * * \param gain_level Set the input amplifier to this amplification * level. * \param input_source Choose between microphone input or linein * input. * \param sample_rate Set the sample rate between 8000 * and 48000 * * \return void * \retval void * */ macro proc audio_init(input_source, sample_rate, AUDIOIN, AUDIOOUT) { /* * We simply call the appropiate handlers and pass values along. * We have volume control to do this. Input and Output sampling rates * are equal. We dont' need different rates. */ RC200AudioInSetInput(input_source); PalAudioInSetSampleRate(AUDIOIN, sample_rate); PalAudioOutSetSampleRate(AUDIOOUT, sample_rate); } /* --- audio_init() --- */ #if !USE_RUNFFT /*! /fn macro proc audio_main(audiodata, AUDIOIN, AUDIOOUT); * * /brief Main audiodriver. This function never returns! It copies the audio * input directly to the audio output * * /param *audiodata pointer to audio information structure. * /param AUDIOIN Audio Input Handler * /param AUDIOOUT Audio Output Handler * * /return Never Returns. * /retval void */ macro proc audio_main(audiodata, AUDIOIN, AUDIOOUT) { /* * Determin the data width for the current platform. */ macro expr IW = PalAudioInGetMaxDataWidthCT(); macro expr OW = PalAudioOutGetMaxDataWidthCT(); signed IW sample_left_in, sample_right_in; signed OW sample_left_out, sample_right_out; while (TRUE) { PalAudioInRead(AUDIOIN, &sample_left_in, &sample_right_in); PalAudioOutWrite(AUDIOOUT, (signed OW)(sample_left_in @ 0), (signed OW)(sample_right_in @ 0)); } } /* --- audio_main() --- */ #else /*! /fn macro proc audio_main(audiodata, AUDIOIN, AUDIOOUT); * * /brief Main audiodriver. This function never returns! It calls the * audiohandlers and stores samples into a global array. Once 64 * Samples are collected it raises a signal AUDIO_READY to let * other processes know it's ready. We use quadruple buffering for * audio input and double buffering for audio output. * * /param audiodata pointer to audio information structure. * /param AUDIOIN Audio Input Handler * /param AUDIOOUT Audio Output Handler * * /return Never Returns. * /retval void */ macro proc audio_main(audiodata, AUDIOIN, AUDIOOUT) { //pointers for double and quadruple buffering: audioptr_in1 = &audio_buffer_in[0]; audioptr_in2 = &audio_buffer_in[64]; audioptr_in3 = &audio_buffer_in[128]; audioptr_in4 = &audio_buffer_in[192]; audioptr_out1 = &audio_buffer_out[0]; audioptr_out2 = &audio_buffer_out[64]; displayptr1 = &audiodata.ifft_info.write[0]; displayptr2 = &audiodata.ifft_info.write[64]; displayptr3 = &audiodata.ifft_info.write[128]; displayptr4 = &audiodata.ifft_info.write[192]; FFT_Sync=0; audiodata.player_state = PLAYER_DISABLED; par { run_fft(audiodata); sample_audio(audiodata, AUDIOIN); output_audio(AUDIOOUT); }//end par } /* --- audio_main() --- */ #endif /*! /fn macro proc run_fft(audiodata); * * /brief FFT loop, waits until 64 samples are read from the audio input * before switching the pointers needed for double and quadruple buffering, * after that sequentially calling the perform_fft, equalize_audio and * perform_ifft functions. * * /param audiodata pointer to audio information structure. * * /return Never Returns. * /retval void */ macro proc run_fft(audiodata) { while(TRUE) { if (FFT_Sync) //if 64 samples are read from ADC... { par { // switch pointers audioptr_in1 = audioptr_in2; audioptr_in2 = audioptr_in3; audioptr_in3 = audioptr_in4; audioptr_in4 = audioptr_in1; audioptr_out1 = audioptr_out2; audioptr_out2 = audioptr_out1; displayptr1=displayptr2; displayptr2=displayptr3; displayptr3=displayptr4; displayptr4=displayptr1; } FFT_Sync = 0; // FFT calculation perform_fft(audioptr_in1); #if PERFORM_FFT_CALCULATION equalize_audio(&audiodata); #endif // inverse FFT calculation perform_ifft(audioptr_out1,displayptr1); } else delay; } } /* --- run_fft() --- */ /*! /fn macro proc sample_audio(ADUIOIN); * * /brief Sampling loop, fills the audio input and output arrays and uses FFT_Sync * to notify the FFT when 64 samples are read from the audio input. * * /param audiodata pointer to audio information structure. * * /return Never Returns. * /retval void */ macro proc sample_audio(audiodata, AUDIOIN) { macro expr IW = PalAudioInGetMaxDataWidthCT(); signed IW LeftNew, RightNew; unsigned 27 blockcount; unsigned 8 not_saturated; unsigned 6 sample_count; unsigned 2 saturation; unsigned 2 track_index; unsigned 1 result; par { while (TRUE) { /* if (FFT_Sync && audiodata.play) //if 64 samples are read from ... { result = load_audio_samples(audioptr_in1, blockcount, WINDOW_SIZE); if (result) { blockcount = 0; } else { blockcount++; } } else { delay; } */ switch (audiodata.player_state) { case PLAYING: if (FFT_Sync) { //if 64 samples can be processed again result = load_audio_samples(audioptr_in1, blockcount, WINDOW_SIZE); if (result) { if(audiodata.player_mode) { blockcount = 0; } else { audiodata.player_state = NEXT_TRACK; } } else { blockcount++; } } else { delay; } break; case STOPPED: blockcount = 0; break; case NEXT_TRACK: if(track_index == NUMBER_OF_TRACKS-1) { track_index = 0; } else { track_index++; } blockcount = 0; change_track(track_index); audiodata.player_state = PLAYING; break; case PREV_TRACK: if(track_index == 0) { track_index = NUMBER_OF_TRACKS-1; } else { track_index--; } blockcount = 0; change_track(track_index); audiodata.player_state = PLAYING; break; case PAUSED: // fall through default: //PLAYER_DISABLED delay; break; } } while (TRUE)//store the samples in the inputbuffer { if (!FFT_Sync) { par { seq { PalAudioInRead(AUDIOIN, &LeftNew, &RightNew); if (audiodata.player_state == PLAYER_DISABLED) { #if HARDWARE_MULTIPLY audioptr_in1[sample_count] = LeftNew; #else audioptr_in1[sample_count] = (LeftNew\\2);//drop 2 LSB's #endif if (LeftNew > 130000) { saturation++; if (!saturation) { audiodata.saturated = TRUE; event_notification ! TRUE; } else { audiodata.saturated = FALSE; } } else { not_saturated++; if (!not_saturated) { audiodata.saturated = FALSE; saturation = 0; event_notification ! TRUE; } } } if ((audiodata.player_state == STOPPED) || (audiodata.player_state == PAUSED)) audioptr_in1[sample_count] = 0; sample_count++; if (!sample_count) { FFT_Sync = TRUE; } } seq { Output_sample = audioptr_out2[sample_count]; } } } else { delay; } } } }/* --- sample_audio() --- */ /*! /fn macro proc output_audio(ADUIOOUT); * * /brief Sampling loop, fills the audio input and output arrays and uses FFT_Sync * to notify the FFT when 64 samples are read from the audio input. * * /param audiodata pointer to audio information structure. * * /return Never Returns. * /retval void */ macro proc output_audio(AUDIOOUT) { macro expr OW = PalAudioOutGetMaxDataWidthCT(); /* * Audio output loop, writes the modified audio samples to the audio output. */ for(;;) { PalAudioOutWrite(AUDIOOUT,(signed OW)(Output_sample @ 0),(signed OW)(Output_sample @ 0)); } }/* --- output_audio() --- */