Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: DokuFFTPACK DokuUSBDevice DokuUSBHost DokuUSBHostWithIso mbed
Fork of Peach_AudioChannelDividerAndCompensator by
main.cpp
00001 /* 00002 * this is free software; you can redistribute it and/or modify 00003 * it under the terms of the GNU General Public License as published by 00004 * the Free Software Foundation; either version 2 of the License, or 00005 * (at your option) any later version. 00006 * 00007 * this software is distributed in the hope that it will be useful, 00008 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 * GNU General Public License for more details. 00011 * 00012 * You should have received a copy of the GNU General Public License 00013 * along with libfftpack; if not, write to the Free Software 00014 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00015 */ 00016 00017 #include "mbed.h" 00018 #include "USBHost6ChDac.h" 00019 #include "USBHostMSD.h" 00020 #include "filter.h" 00021 #include "USBAudio.h" 00022 00023 #if defined(TARGET_RZ_A1H) 00024 #include "usb_host_setting.h" 00025 #else 00026 #define USB_HOST_CH 0 00027 #endif 00028 00029 //data size of receiving buffer in long word (32767samples 16bit stereo) 00030 #define IN_DWORDS 32768 00031 #define IN_BANKS 2 00032 //data size of sending buffer in long word (32767samples 16bit 6ch) 00033 #define OUT_DWORDS (3 * IN_DWORDS) 00034 #define OUT_BANKS 2 00035 //data size of silence data in long word (48ksps 16bit 6ch 100msec) 00036 #define NULL_DWORDS (48 * 2 * 6 * 100 / 4) 00037 00038 //shows USB audio is attached or not 00039 extern int USB_Audio_Attached; 00040 //receiving buffer (2 banks) 00041 static volatile uint32_t BufR[IN_BANKS][IN_DWORDS]; 00042 //sending buffer (2 banks) 00043 static volatile uint32_t BufW[OUT_BANKS][OUT_DWORDS]; 00044 //silence data buffer to adjust buffer volume 00045 static volatile uint32_t BufNull[NULL_DWORDS] = {}; 00046 //overflow flag of FFT 00047 int FFTOverFlow = 0; 00048 00049 //push button on the board 00050 DigitalIn button(USER_BUTTON0); 00051 00052 //shows adjustment for buffer short or full is done 00053 DigitalOut LedR(LED1); 00054 DigitalOut LedG(LED2); 00055 //shows FFT is in process 00056 DigitalOut LedB(LED3); 00057 00058 //USBDAC host 00059 USBHostDac *pusbdac; 00060 00061 //receive buffer bank 0 or 1 ready 00062 Semaphore semR0(0); 00063 Semaphore semR1(0); 00064 //send buffer bank 0 or 1 ready 00065 Semaphore semW0(0); 00066 Semaphore semW1(0); 00067 00068 Semaphore *semR[2] = {&semR0, &semR1}; 00069 Semaphore *semW[2] = {&semW0, &semW1}; 00070 00071 //measures latency of semaphore waiting 00072 Timer Tmr; 00073 00074 //target latency for buffer slack in mili sec (88msec for buffer full at 11 ITDs) 00075 #define TARGET_LATENCY 40 00076 //allowance of latency 00077 //latency is controled in TARGET_LATENCY - LATENCY_ALLOWANCE to TARGET_LATENCY + LATENCY_ALLOWANCE 00078 #define LATENCY_ALLOWANCE 30 00079 //output byte number to get 1msecond adjustment (48ksps 16bit 6ch at 1milisec) 00080 #define OUT_BYTE_PER_MILISEC (48*2*6) 00081 00082 //sound data sending task 00083 void UsbSend(void const* arg) 00084 { 00085 //usb host 00086 USBHostDac * p_usbdac = (USBHostDac *)arg; 00087 //bank number of buffer (0 or 1) 00088 int Bank = 0; 00089 //waiting latency of semaphore 00090 int Latency; 00091 //adjust time in mili second 00092 int Adjmsec; 00093 //number of skipping byte 00094 int SkipBytes; 00095 00096 Tmr.start(); 00097 for(;;) 00098 { 00099 //riset adjusting display 00100 LedR = 0; 00101 //reset timer to measure latency of semaphore 00102 Tmr.reset(); 00103 semW[Bank]->wait(); 00104 //get latency 00105 Latency = Tmr.read_ms(); 00106 printf("Latency:%d\n",Latency); 00107 //if semahore's latency is too large, data shortage has happen 00108 if(Latency > (TARGET_LATENCY + LATENCY_ALLOWANCE)) 00109 { 00110 //get period for adjustment 00111 Adjmsec = Latency - TARGET_LATENCY; 00112 if(Adjmsec > TARGET_LATENCY) Adjmsec = TARGET_LATENCY; 00113 printf("Recover %dmsec\n",Adjmsec); 00114 //put silence data into sending queue to prevent data shortage 00115 p_usbdac->send((uint8_t *)BufNull, Adjmsec * OUT_BYTE_PER_MILISEC, false); 00116 //data skip is unnecessary for buffer have some vacancy 00117 SkipBytes = 0; 00118 //Show adjusting happend 00119 LedR = 1; 00120 } 00121 //if semahore's latency is too small, buffer is nearly full 00122 else if(Latency < (TARGET_LATENCY - LATENCY_ALLOWANCE)) 00123 { 00124 //get period for adjustment 00125 Adjmsec = TARGET_LATENCY - Latency; 00126 if(Adjmsec > TARGET_LATENCY) Adjmsec = TARGET_LATENCY; 00127 //decrease sending data, to make some vacancy on the buffer 00128 SkipBytes = Adjmsec * OUT_BYTE_PER_MILISEC; 00129 printf("Skip %dmsec %dByte\n",Adjmsec,SkipBytes); 00130 //Show adjusting happend 00131 LedR = 1; 00132 } 00133 else 00134 { 00135 //no demand for data skip because buffer have regular vacancy 00136 SkipBytes = 0; 00137 } 00138 //send music data 00139 p_usbdac->send((uint8_t *)&BufW[Bank][SkipBytes / 4], OUT_DWORDS * 4 - SkipBytes, false); 00140 //next bank 00141 Bank++; 00142 Bank &= 1; 00143 } 00144 } 00145 00146 //FFT solving task 00147 void FFTSolve(void const* arg) 00148 { 00149 int Bank = 0; 00150 for(;;) 00151 { 00152 //wait for FFT sorce data ready 00153 semR[Bank]->wait(); 00154 //show FFT is in work 00155 LedB = 1; 00156 //apply FIR filters and write the result on the buffer 00157 FFTOverFlow = FLT_Filter((int16_t *)(BufW[Bank]),(int16_t *)(BufR[Bank]),!button); 00158 // FFTOverFlow = FLT_Through((int16_t *)(BufW[Bank]),(int16_t *)BufR[Bank]); 00159 //show FFT ended 00160 LedB = 0; 00161 //order to send the FFT result 00162 semW[Bank]->release(); 00163 //next bank 00164 Bank++; 00165 Bank &= 1; 00166 } 00167 } 00168 00169 //receive 32768 sample of audio input from USB audio device 00170 int usbdevice_receive32k(USBAudio *paudio,uint32_t *Buf) 00171 { 00172 int i; 00173 00174 //repat reading in 1 second 00175 for(i = 0;i < 70;i++) 00176 { 00177 //attempting to read 00178 if(paudio->read32k(Buf)) 00179 { 00180 //returns 1 if correctly read 00181 return 1; 00182 } 00183 else 00184 { 00185 //if read error, wait a moment and retry 00186 Thread::wait(10); 00187 } 00188 } 00189 //returns 0 if read error 00190 return 0; 00191 } 00192 00193 int main() 00194 { 00195 //receiving bank (0 or 1) 00196 int Bank = 0; 00197 //receiving result 00198 int rc = 0; 00199 //input mode 1:USB audio device 0:LINE-IN of USB DAC 00200 int InModeUSB = 1; 00201 00202 printf("\n\nStarted\n"); 00203 00204 //initializing silence buffer 00205 memset((uint8_t *)BufNull,0,NULL_DWORDS * 4); 00206 00207 //USB audio device initialize 00208 static USBAudio audio(48000, 2, 8000, 1, 0x7180, 0x7500); 00209 00210 //start Mass Strage Device host 00211 USBHostMSD msd("usb"); 00212 //start Audio host 00213 USBHostDac usbdac; 00214 //get pointer to Audio host to use it in other function 00215 pusbdac = &usbdac; 00216 00217 //wait connection of MSD 00218 while(!msd.connect()) 00219 { 00220 printf("Attempting to connect a MSD\n"); 00221 Thread::wait(500); 00222 } 00223 00224 //initializing FIR filters (setting up FFT and reading filter coefficients) 00225 while(! FLT_Init()) 00226 { 00227 printf("Filter initialization error\n"); 00228 Thread::wait(500); 00229 } 00230 00231 //create sending and FFT task 00232 Thread SendTask(UsbSend, &usbdac, osPriorityNormal, 1024 * 8); 00233 Thread FFTTask(FFTSolve, &usbdac, osPriorityNormal, 1024 * 8); 00234 00235 for(;;) 00236 { 00237 // 00238 // CONNECTION WITH USB-DAC 00239 // 00240 //if USB-DAC is disconnected 00241 if(! pusbdac->connected()) 00242 { 00243 //connect USB-DAC 00244 pusbdac->connect(); 00245 } 00246 // 00247 // INPUT SWITCHING 00248 // 00249 //if now switched to USB_INPUT mode 00250 if(InModeUSB) 00251 { 00252 //if USB_INPUT is detached 00253 if(! USB_Audio_Attached) 00254 { 00255 //select LINE_INPUT for input 00256 printf("Switched to LINE-IN\n"); 00257 InModeUSB = 0; 00258 } 00259 } 00260 //if now switched to LINE_INPUT mode 00261 else 00262 { 00263 //if USB_INPUT is attached 00264 if(USB_Audio_Attached) 00265 { 00266 //select USB_INPUT for input 00267 printf("Switched to USB-IN\n"); 00268 InModeUSB = 1; 00269 } 00270 } 00271 // 00272 // RECEIVING AUDIO DATA 00273 // 00274 //if using USB-INPUT 00275 if(InModeUSB) 00276 { 00277 //receive USB-IN 00278 rc = usbdevice_receive32k(&audio,(uint32_t *)BufR[Bank]); 00279 } 00280 //if using LINE-IN 00281 else 00282 { 00283 //receive LINE-IN 00284 rc = usbdac.receive((uint8_t *)(BufR[Bank]), IN_DWORDS * 4); 00285 } 00286 // 00287 // ERROR HANDLING and ORDERING TO START FFT 00288 // 00289 //if error occurs 00290 if(! rc) 00291 { 00292 //order send task to full some data to prevent data short 00293 //Recover = 1; 00294 //clear all buffers to mute 00295 audio.clear32k(); 00296 FLT_Clear(); 00297 memset((uint8_t *)BufR,0,IN_DWORDS * IN_BANKS * 4); 00298 memset((uint8_t *)BufW,0,OUT_DWORDS * OUT_BANKS * 4); 00299 } 00300 //if read correctly 00301 else 00302 { 00303 //order to start FFT 00304 semR[Bank]->release(); 00305 //select next bank 00306 Bank++; 00307 Bank &= 1; 00308 } 00309 } 00310 }
Generated on Mon Jul 18 2022 17:22:51 by
1.7.2
