Audio channel divider and compensator.

Dependencies:   DokuFFTPACK DokuUSBDevice DokuUSBHost DokuUSBHostWithIso mbed

Fork of Peach_AudioChannelDividerAndCompensator by doku newon

日本語の説明は後半にあります。

Outline

This is audio channel dividing filter for multi-way multi-amplifier systems with compensation for system and room response. This program uses 32768 taps of real time 6ch floating point FIR (by FFT and superimpose) for accurate compensation of low frequency. Either USB digital audio stream (USB1) or analog audio signal (LINE-IN of USB-DAC) can be accepted. GR-Peach divide up them into six channel (Low,Mid,High each L,R). Then outputs them to the multi-channel USB-DAC as a USB host (USB0). 32767 taps of FIR coefficient is given by the files in the USB MSD (USB0).
GR-Peach's superabundant process power solves real time 6ch/32kTaps floating point audio FIR in textbook method without any optimization.
/media/uploads/dokunewon/--2.jpg

Sorry

This cord works but doesn't tested completely, can work with multi-channnel USB-DAC CM6206 chip inside.

Connection

To use this program, connect USB0 of GR-Peach to a self powered USBHUB, a multi-channel USB-DAC(CM6206 chip inside / e.c.DN-USBSA6CHOPThttp://www.donya.jp/site/item/item_20087.html or RA-AUD51) and a USB mass storage device (coefficient files are saved) to the USBHUB as shown above.
If you would like to accept digital audio stream (16bit/48ksps) as a USB audio device, connect USB1 of GR-Peach to the PC. If not, analog stereo audio signal is accepted.

Filter setting

You can get your favorite cross-over and compensation characteristics modifying FIR coefficient files named Fir_Ch0.snd to Fir_Ch5.snd. Coefficient files are signed 16 bit integer raw formatted sound file (without any header) having time domain responses of the FIRs. Coefficient file have 65536 samples of filter response. but second-half portion of the file (32768 samples) must be zero to work superimpose correctly. If you want minimum phase FIR, filter impulse will be placed at the first sample of the file. If you want liner phase FIR, filter impulse will be placed at 16384 sample of the file.

Sample coefficient files

Sample coefficient files are shown below. store below files in Root folder of USB mass storage device before running the program. These are files for two way systems. Since flatness of frequency response is archived by the compensation, full range speaker works very well without tweeter. In below files, ch0 and ch1 for full range speakers, ch2 and ch3 for low range speakers (woofers), ch4 and ch5 are not used. Of cause, system compensation coefficient is differ according to speaker unit, speaker enclosure, room, and amplifier. Below samples are for my speakers and room.

Compensated coefficient file with channel divider

ch0:full range(high):left:/media/uploads/dokunewon/fir_ch0.snd
ch1:full range(high):right:/media/uploads/dokunewon/fir_ch1.snd
ch2:woofer(mid):left:/media/uploads/dokunewon/fir_ch2.snd
ch3:woofer(mid):right:/media/uploads/dokunewon/fir_ch3.snd
ch4:not_used(low):left:/media/uploads/dokunewon/fir_ch4.snd
ch4:not_used(low):right:/media/uploads/dokunewon/fir_ch5.snd

channel divider without compensation (pushing the user button on the GR-Peach, below coefficients are used)

ch0:full range(high):left:/media/uploads/dokunewon/fir_ch0nc.snd
ch1:full range(high):right:/media/uploads/dokunewon/fir_ch1nc.snd
ch2:woofer(mid):left:/media/uploads/dokunewon/fir_ch2nc.snd
ch3:woofer(mid):right:/media/uploads/dokunewon/fir_ch3nc.snd
ch4:not_used(low):left:/media/uploads/dokunewon/fir_ch4nc.snd
ch4:not_used(low):right:/media/uploads/dokunewon/fir_ch5nc.snd

Filter bypass test coefficient

/media/uploads/dokunewon/fir_bypass.snd

Gain of each Filter

/media/uploads/dokunewon/gains.txt

Measuring system and generating filter coefficient

These coefficient files are generated by a home made audio analyzer tool works on PC below.
/media/uploads/dokunewon/inversex90.zip
Latest beta release /media/uploads/dokunewon/inversex72.zip (Smallest number shows the latest one)
/media/uploads/dokunewon/inversex.jpg
Use above tool reading below manual.
/media/uploads/dokunewon/inversex84.pdf
Latest beta release /media/uploads/dokunewon/inversex72.pdf (Smallest number shows the latest one)
Using this tool, you can configure cross-over frequency and filter dimension for two or three way multi-way multi-amplifier system, measure response of your room and system, generate inverse response transfer function using unique and refined algorithm to create compensation FIR coefficient.

Improvement in frequency characteristic by compensation

Average spectrum of white noise before compensation (By 2 way system High:F77G98-6 x 1 Low:F77G98-6 x 8)
/media/uploads/dokunewon/uncompensated2.jpg
Average spectrum of white noise after compensation (By 2 way system High:F77G98-6 x 1 Low:F77G98-6 x 8)
/media/uploads/dokunewon/compensated2.jpg

Compensation example

Sorry. Some car noise from the road fronting my house recorded together.
Recorded playback sound by 2 way system (High:F77G98-6 x 1 Low:F77G98-6 x 8)
Early part : normal playback / latter part : compensated playback.
/media/uploads/dokunewon/samplef77g98-6.mp3
Recorded playback sound by low-cost powered small speaker Roland MA-8 (channel divider is not used)
Early part : normal playback / latter part : compensated playback.
/media/uploads/dokunewon/playbacksample.mp3
/media/uploads/dokunewon/ma8.jpg

概要

システムの特性補償を行なうマルチアンプマルチウェイシステム用のオーディオチャンネルデバイダです。低音を正確に補正するために、32768タップのFIRを使用しています。GR-Peachの有り余る処理力で、教科書通りのフィルタアルゴリズムが(最適化なしで!)リアルタイムにオーディオ信号を処理します。
本ソフトはUSB1端子に入力されたデジタルステレオ音声信号(48kサンプル16ビットの)か、USB-DACのLINE-IN端子に入力されたアナログステレオ音声信号を、システム特性を補償すると同時に左右各3チャンネルに帯域分割して、マルチチャンネルUSB-DACに出力します。

おわび

このプログラムは一応動くのですが完全にテストされていません。USB-DACは内部にCM6206を使用したものだけに対応しています。
/media/uploads/dokunewon/--2.jpg

接続

上の図のように、USB0には(できればセルフパワーの)USBHUBを接続し、HUBには、マルチチャンネルUSBDAC(CM6206を使用した、DN-USBSA6CHOPThttp://www.donya.jp/site/item/item_20087.html あるいは RA-AUD51)とFIR特性ファイルを記録したUSBメモリを接続します。
デジタルオーディオ信号を入力する場合は、USB1端子にPC等を接続します。USB1端子に何も繋がなければ、USB-DACのLINE-IN端子のアナログオーディオ信号が入力されます。

フィルタの設定

FIR特性ファイル(Fir_Ch0.snd ~ Fir_Ch5.snd)を変更することで、好みの補正やクロスオーバー特性を得ることができます。特性ファイルはFIRの時間領域の応答を記録した16ビット符号付整数形式のヘッダなしモノラルRAW波形データです。特性ファイルには65536サンプルのフィルタ応答が記録されていますが、後ろ半分は重畳処理の都合でゼロとします。

見本の特性ファイル

見本の特性ファイルを次に示します。これらは、2ウェイシステム用のファイルです。これらのファイルはUSBMSDのルートフォルダに配置します。システム特性の補正によってフラットな周波数特性が実現されるので、トゥイータ無しのフルレンジスピーカーでも良い結果が得られます。チャンネル0と1がフルレンジ、2と3がウーファ、4と5は今回使用しません。もちろんシステムの補償はユニット、エンクロジャー、部屋、アンプ等によって変化します。下の例は、私のスピーカーと部屋のためのものです。(フルレンジは、F77G98-6左右各1本、ウーファはF77G98-6左右各8本を使用しています)

チャンネルデバイダの特性(補償付き)

ch0:full range(high):left:/media/uploads/dokunewon/fir_ch0.snd
ch1:full range(high):right:/media/uploads/dokunewon/fir_ch1.snd
ch2:woofer(mid):left:/media/uploads/dokunewon/fir_ch2.snd
ch3:woofer(mid):right:/media/uploads/dokunewon/fir_ch3.snd
ch4:not_used(low):left:/media/uploads/dokunewon/fir_ch4.snd
ch4:not_used(low):right:/media/uploads/dokunewon/fir_ch5.snd

チャンネルデバイダの特性(補償なし:ピーチの押しボタンを押すと、こちらの特性に切り替わります)

ch0:full range(high):left:/media/uploads/dokunewon/fir_ch0nc.snd
ch1:full range(high):right:/media/uploads/dokunewon/fir_ch1nc.snd
ch2:woofer(mid):left:/media/uploads/dokunewon/fir_ch2nc.snd
ch3:woofer(mid):right:/media/uploads/dokunewon/fir_ch3nc.snd
ch4:not_used(low):left:/media/uploads/dokunewon/fir_ch4nc.snd
ch4:not_used(low):right:/media/uploads/dokunewon/fir_ch5nc.snd

テスト用のバイパスフィルタ

/media/uploads/dokunewon/fir_bypass.snd

各フィルタのゲイン

/media/uploads/dokunewon/gains.txt

システムの測定とフィルタ特性の生成

上記の特性ファイルは次の自作のPC用測定分析ツールで生成しています。
/media/uploads/dokunewon/inversex90.zip
最新のベータ版 /media/uploads/dokunewon/inversex72.zip (数字が小さい方が最新です) /media/uploads/dokunewon/inversex.jpg
使い方は次のファイルを参照してください。
/media/uploads/dokunewon/inversex84.pdf
最新のベータ版 /media/uploads/dokunewon/inversex72.pdf (数字が小さい方が最新です)
このツールを使用して、クロスオーバーの周波数や次数、システム特性の測定、補償用の逆フィルタの生成が可能です。

補償による周波数特性の改善

補償前のホワイトノイズの平均スペクトラム (By 2 way system High:F77G98-6 x 1 Low:F77G98-6 x 8)
/media/uploads/dokunewon/uncompensated2.jpg
補償後のホワイトノイズの平均スペクトラム (By 2 way system High:F77G98-6 x 1 Low:F77G98-6 x 8)
/media/uploads/dokunewon/compensated2.jpg

補償による音声の変化

国道を通る自動車の音なども一緒に入ってますが、悪しからず。
2ウェイマルチアンプシステム (High:F77G98-6 x 1 Low:mid:F77G98-6 x 8)
前半:通常再生音/後半:補償再生音
/media/uploads/dokunewon/samplef77g98-6.mp3
低価格小型パワードスピーカー Roland MA-8
前半:通常再生音/後半:補償再生音
/media/uploads/dokunewon/playbacksample.mp3
/media/uploads/dokunewon/ma8.jpg

Committer:
dokunewon
Date:
Mon Oct 19 00:27:51 2015 +0000
Revision:
11:064c590a51f9
Parent:
10:5e85f83e8e8f
Child:
12:d12709edf53d
Improve output buffer control, monitoring semaphore's waiting latency.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dokunewon 4:1e3019bcd565 1 /*
dokunewon 4:1e3019bcd565 2 * this is free software; you can redistribute it and/or modify
dokunewon 4:1e3019bcd565 3 * it under the terms of the GNU General Public License as published by
dokunewon 4:1e3019bcd565 4 * the Free Software Foundation; either version 2 of the License, or
dokunewon 4:1e3019bcd565 5 * (at your option) any later version.
dokunewon 4:1e3019bcd565 6 *
dokunewon 4:1e3019bcd565 7 * this software is distributed in the hope that it will be useful,
dokunewon 4:1e3019bcd565 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
dokunewon 4:1e3019bcd565 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dokunewon 4:1e3019bcd565 10 * GNU General Public License for more details.
dokunewon 4:1e3019bcd565 11 *
dokunewon 4:1e3019bcd565 12 * You should have received a copy of the GNU General Public License
dokunewon 4:1e3019bcd565 13 * along with libfftpack; if not, write to the Free Software
dokunewon 4:1e3019bcd565 14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
dokunewon 4:1e3019bcd565 15 */
dokunewon 4:1e3019bcd565 16
dkato 0:39320363f99f 17 #include "mbed.h"
dokunewon 6:3a337a5e5aa7 18 #include "USBHost6ChDac.h"
dkato 0:39320363f99f 19 #include "USBHostMSD.h"
dokunewon 4:1e3019bcd565 20 #include "filter.h"
dokunewon 4:1e3019bcd565 21 #include "USBAudio.h"
dkato 0:39320363f99f 22
dkato 1:82fe51d45902 23 #if defined(TARGET_RZ_A1H)
dkato 1:82fe51d45902 24 #include "usb_host_setting.h"
dkato 1:82fe51d45902 25 #else
dkato 1:82fe51d45902 26 #define USB_HOST_CH 0
dkato 1:82fe51d45902 27 #endif
dkato 1:82fe51d45902 28
dokunewon 11:064c590a51f9 29 #define IN_DWORDS 32768 //data size in long word buffer 32767 sample stereo
dokunewon 6:3a337a5e5aa7 30 #define IN_BANKS 2
dokunewon 11:064c590a51f9 31 #define OUT_DWORDS (3 * IN_DWORDS) //data size in long word buffer 32767 sample stereo * 3
dokunewon 6:3a337a5e5aa7 32 #define OUT_BANKS 2
dokunewon 11:064c590a51f9 33 #define NULL_DWORDS (48 * 2 * 6 * 100 / 4) //silenc sound data for 100msec
dokunewon 4:1e3019bcd565 34
dokunewon 6:3a337a5e5aa7 35 extern int USB_Audio_Attached;
dokunewon 6:3a337a5e5aa7 36 static volatile uint32_t BufR[IN_BANKS][IN_DWORDS];
dokunewon 6:3a337a5e5aa7 37 static volatile uint32_t BufW[OUT_BANKS][OUT_DWORDS];
dokunewon 6:3a337a5e5aa7 38 static volatile uint32_t BufNull[NULL_DWORDS] = {};
dokunewon 6:3a337a5e5aa7 39 int Recover = 1;
dokunewon 6:3a337a5e5aa7 40 int FFTOverFlow = 0;
dokunewon 4:1e3019bcd565 41
dkato 0:39320363f99f 42 DigitalIn button(USER_BUTTON0);
dkato 0:39320363f99f 43
dokunewon 4:1e3019bcd565 44 DigitalOut LedR(LED1);
dokunewon 4:1e3019bcd565 45 DigitalOut LedG(LED2);
dokunewon 4:1e3019bcd565 46 DigitalOut LedB(LED3);
dkato 0:39320363f99f 47
dokunewon 4:1e3019bcd565 48 //USBDAC
dokunewon 4:1e3019bcd565 49 USBHostDac *pusbdac;
dkato 1:82fe51d45902 50
dokunewon 6:3a337a5e5aa7 51 Semaphore semW0(0);
dokunewon 6:3a337a5e5aa7 52 Semaphore semR0(0);
dokunewon 6:3a337a5e5aa7 53 Semaphore semW1(0);
dokunewon 6:3a337a5e5aa7 54 Semaphore semR1(0);
dokunewon 6:3a337a5e5aa7 55
dokunewon 9:2ecebace33b1 56 Timer Tmr;
dokunewon 9:2ecebace33b1 57
dokunewon 11:064c590a51f9 58 #define TARGET_BUFFER_MARGIN 20 //88 for buffer full at 11 ITDs
dokunewon 11:064c590a51f9 59 #define OUT_BYTE_PER_MILISEC (48*2*6) //48ksps 2byte 6ch / milisec
dokunewon 11:064c590a51f9 60
dokunewon 9:2ecebace33b1 61 void UsbSend(void const* arg)
dokunewon 9:2ecebace33b1 62 {
dokunewon 11:064c590a51f9 63 int Bank = 0;
dokunewon 11:064c590a51f9 64 int Latency,Adjmsec;
dokunewon 6:3a337a5e5aa7 65 USBHostDac * p_usbdac = (USBHostDac *)arg;
dokunewon 11:064c590a51f9 66 int SkipBytes;
dokunewon 6:3a337a5e5aa7 67
dokunewon 9:2ecebace33b1 68 Tmr.start();
dokunewon 6:3a337a5e5aa7 69 for(;;)
dokunewon 6:3a337a5e5aa7 70 {
dokunewon 11:064c590a51f9 71 //reset timer to measure waiting time of semahore
dokunewon 11:064c590a51f9 72 Tmr.reset();
dokunewon 11:064c590a51f9 73 if(! Bank)
dokunewon 11:064c590a51f9 74 {
dokunewon 11:064c590a51f9 75 //wait FFT result prepaired
dokunewon 11:064c590a51f9 76 semW0.wait();
dokunewon 11:064c590a51f9 77 }
dokunewon 11:064c590a51f9 78 else
dokunewon 11:064c590a51f9 79 {
dokunewon 11:064c590a51f9 80 //wait FFT result prepaired
dokunewon 11:064c590a51f9 81 semW1.wait();
dokunewon 11:064c590a51f9 82 }
dokunewon 11:064c590a51f9 83 Latency = Tmr.read_ms();
dokunewon 11:064c590a51f9 84 printf("Latency:%d\n",Latency);
dokunewon 11:064c590a51f9 85 //if semahore's waiting time is too long , data shortage have happen
dokunewon 11:064c590a51f9 86 if(Latency > 70)
dokunewon 4:1e3019bcd565 87 {
dokunewon 11:064c590a51f9 88 Adjmsec = Latency - 40;
dokunewon 11:064c590a51f9 89 //it is not nessesary to fill over ITD buffer size
dokunewon 11:064c590a51f9 90 if(Adjmsec > 40) Adjmsec = 40;
dokunewon 11:064c590a51f9 91 printf("Recover %dmsec\n",Adjmsec);
dokunewon 10:5e85f83e8e8f 92 //put null data into sending queue to prevent data shortage
dokunewon 11:064c590a51f9 93 p_usbdac->send((uint8_t *)BufNull, Adjmsec * OUT_BYTE_PER_MILISEC, false);
dokunewon 11:064c590a51f9 94 //no demand for data skip because buffer have some vacancy
dokunewon 11:064c590a51f9 95 SkipBytes = 0;
dokunewon 6:3a337a5e5aa7 96 }
dokunewon 11:064c590a51f9 97 //if semahore's waiting time is too short, buffer is nearly full
dokunewon 11:064c590a51f9 98 else if(Latency < 10)
dokunewon 11:064c590a51f9 99 {
dokunewon 11:064c590a51f9 100 Adjmsec = 40 - Latency;
dokunewon 11:064c590a51f9 101 if(Adjmsec > 40) Adjmsec = 40;
dokunewon 11:064c590a51f9 102 //decrease sending data, to make some vacancy on the buffer
dokunewon 11:064c590a51f9 103 SkipBytes = Adjmsec * OUT_BYTE_PER_MILISEC;
dokunewon 11:064c590a51f9 104 printf("Skip %dmsec %dByte\n",Adjmsec,SkipBytes);
dokunewon 11:064c590a51f9 105 }
dokunewon 11:064c590a51f9 106 else
dokunewon 11:064c590a51f9 107 {
dokunewon 11:064c590a51f9 108 //no demand for data skip because buffer have regular vacancy
dokunewon 11:064c590a51f9 109 SkipBytes = 0;
dokunewon 11:064c590a51f9 110 }
dokunewon 6:3a337a5e5aa7 111 LedB = 1;
dokunewon 6:3a337a5e5aa7 112 //send music data
dokunewon 11:064c590a51f9 113 p_usbdac->send((uint8_t *)&BufW[Bank][SkipBytes / 4], OUT_DWORDS * 4 - SkipBytes, false);
dokunewon 6:3a337a5e5aa7 114 LedB = 0;
dokunewon 11:064c590a51f9 115 //next bank
dokunewon 11:064c590a51f9 116 Bank++;
dokunewon 11:064c590a51f9 117 Bank &= 1;
dokunewon 6:3a337a5e5aa7 118 }
dokunewon 6:3a337a5e5aa7 119 }
dokunewon 6:3a337a5e5aa7 120
dokunewon 6:3a337a5e5aa7 121 void FFTSolve(void const* arg) {
dokunewon 6:3a337a5e5aa7 122 for(;;)
dokunewon 6:3a337a5e5aa7 123 {
dokunewon 6:3a337a5e5aa7 124 semR0.wait();
dokunewon 6:3a337a5e5aa7 125 LedG = 1;
dokunewon 6:3a337a5e5aa7 126 //入力をフィルタして出力バッファに書き込む
dokunewon 6:3a337a5e5aa7 127 FFTOverFlow = FLT_Filter((int16_t *)(BufW[0]),(int16_t *)(BufR[0]),!button);
dokunewon 6:3a337a5e5aa7 128 // FFTOverFlow = FLT_Through((int16_t *)(BufW[0]),(int16_t *)BufR[0]);
dokunewon 6:3a337a5e5aa7 129 LedG = 0;
dokunewon 6:3a337a5e5aa7 130 semW0.release();
dokunewon 4:1e3019bcd565 131
dokunewon 6:3a337a5e5aa7 132 semR1.wait();
dokunewon 6:3a337a5e5aa7 133 LedG = 1;
dokunewon 6:3a337a5e5aa7 134 //入力をフィルタして出力バッファに書き込む
dokunewon 6:3a337a5e5aa7 135 FFTOverFlow = FLT_Filter((int16_t *)(BufW[1]),(int16_t *)(BufR[1]),!button);
dokunewon 6:3a337a5e5aa7 136 // FFTOverFlow = FLT_Through((int16_t *)(BufW[1]),(int16_t *)BufR[1]);
dokunewon 6:3a337a5e5aa7 137 LedG = 0;
dokunewon 6:3a337a5e5aa7 138 semW1.release();
dkato 0:39320363f99f 139 }
dkato 0:39320363f99f 140 }
dokunewon 4:1e3019bcd565 141
dokunewon 6:3a337a5e5aa7 142 //receive 32768 sample of audio input from USB
dokunewon 6:3a337a5e5aa7 143 int usbdevice_receive32k(USBAudio *paudio,uint32_t *Buf)
dokunewon 6:3a337a5e5aa7 144 {
dokunewon 6:3a337a5e5aa7 145 int i;
dokunewon 6:3a337a5e5aa7 146
dokunewon 6:3a337a5e5aa7 147 //repat reading in 1 second
dokunewon 9:2ecebace33b1 148 for(i = 0;i < 62;i++)
dokunewon 6:3a337a5e5aa7 149 {
dokunewon 6:3a337a5e5aa7 150 //attempting to read
dokunewon 6:3a337a5e5aa7 151 if(paudio->read32k(Buf))
dokunewon 6:3a337a5e5aa7 152 {
dokunewon 6:3a337a5e5aa7 153 //returns 1 if correctly read
dokunewon 6:3a337a5e5aa7 154 return 1;
dokunewon 6:3a337a5e5aa7 155 }
dokunewon 6:3a337a5e5aa7 156 else
dokunewon 6:3a337a5e5aa7 157 {
dokunewon 9:2ecebace33b1 158 //if read error, wait a moment and retry
dokunewon 6:3a337a5e5aa7 159 Thread::wait(10);
dokunewon 6:3a337a5e5aa7 160 }
dokunewon 6:3a337a5e5aa7 161 }
dokunewon 6:3a337a5e5aa7 162 //returns 0 if read error
dokunewon 6:3a337a5e5aa7 163 return 0;
dokunewon 6:3a337a5e5aa7 164 }
dokunewon 6:3a337a5e5aa7 165
dokunewon 4:1e3019bcd565 166 int main()
dokunewon 4:1e3019bcd565 167 {
dokunewon 6:3a337a5e5aa7 168 int Bank = 0;
dokunewon 6:3a337a5e5aa7 169 int rc = 0;
dokunewon 6:3a337a5e5aa7 170 int InModeUSB = 1;
dokunewon 6:3a337a5e5aa7 171
dokunewon 6:3a337a5e5aa7 172 printf("\n\nStarted\n");
dokunewon 4:1e3019bcd565 173
dokunewon 11:064c590a51f9 174 //initializing silence buffer
dokunewon 11:064c590a51f9 175 memset((uint8_t *)BufNull,0,NULL_DWORDS * 4);
dokunewon 11:064c590a51f9 176
dokunewon 6:3a337a5e5aa7 177 //USB sound device initialize
dokunewon 6:3a337a5e5aa7 178 static USBAudio audio(48000, 2, 8000, 1, 0x7180, 0x7500);
dokunewon 4:1e3019bcd565 179
dokunewon 6:3a337a5e5aa7 180 //start Mass Strage Device host
dokunewon 4:1e3019bcd565 181 USBHostMSD msd("usb");
dokunewon 6:3a337a5e5aa7 182 //start Audio host
dokunewon 4:1e3019bcd565 183 USBHostDac usbdac;
dokunewon 6:3a337a5e5aa7 184 //get pointer to Audio host to use it in other function
dokunewon 4:1e3019bcd565 185 pusbdac = &usbdac;
dokunewon 4:1e3019bcd565 186
dokunewon 6:3a337a5e5aa7 187 //wait connection of MSD
dokunewon 4:1e3019bcd565 188 while(!msd.connect())
dokunewon 4:1e3019bcd565 189 {
dokunewon 6:3a337a5e5aa7 190 printf("Attempting to connect a MSD\n");
dokunewon 4:1e3019bcd565 191 Thread::wait(500);
dokunewon 4:1e3019bcd565 192 }
dokunewon 4:1e3019bcd565 193
dokunewon 6:3a337a5e5aa7 194 //initializing FIR filters (setting up FFT and reading filter coefficient)
dokunewon 6:3a337a5e5aa7 195 while(! FLT_Init())
dokunewon 4:1e3019bcd565 196 {
dokunewon 6:3a337a5e5aa7 197 printf("Filter initialization error\n");
dokunewon 4:1e3019bcd565 198 Thread::wait(500);
dokunewon 4:1e3019bcd565 199 }
dokunewon 4:1e3019bcd565 200
dokunewon 6:3a337a5e5aa7 201 //USBオーディオ送受信スレッドの生成
dokunewon 6:3a337a5e5aa7 202 Thread SendTask(UsbSend, &usbdac, osPriorityNormal, 1024 * 8);
dokunewon 6:3a337a5e5aa7 203 Thread FFTTask(FFTSolve, &usbdac, osPriorityNormal, 1024 * 8);
dokunewon 4:1e3019bcd565 204
dokunewon 6:3a337a5e5aa7 205 for(;;)
dokunewon 6:3a337a5e5aa7 206 {
dokunewon 6:3a337a5e5aa7 207 //
dokunewon 6:3a337a5e5aa7 208 // CONNECTION WITH USB-DAC
dokunewon 6:3a337a5e5aa7 209 //
dokunewon 6:3a337a5e5aa7 210 //if USB-DAC is disconnected
dokunewon 6:3a337a5e5aa7 211 if(! pusbdac->connected())
dokunewon 6:3a337a5e5aa7 212 {
dokunewon 6:3a337a5e5aa7 213 //connect USB-DAC
dokunewon 6:3a337a5e5aa7 214 pusbdac->connect();
dokunewon 6:3a337a5e5aa7 215 }
dokunewon 6:3a337a5e5aa7 216 //
dokunewon 6:3a337a5e5aa7 217 // INPUT SWITCHING
dokunewon 6:3a337a5e5aa7 218 //
dokunewon 6:3a337a5e5aa7 219 //if now switched to USB_INPUT mode
dokunewon 6:3a337a5e5aa7 220 if(InModeUSB)
dokunewon 6:3a337a5e5aa7 221 {
dokunewon 6:3a337a5e5aa7 222 //if USB_INPUT is detached
dokunewon 6:3a337a5e5aa7 223 if(! USB_Audio_Attached)
dokunewon 6:3a337a5e5aa7 224 {
dokunewon 6:3a337a5e5aa7 225 //select LINE_INPUT for input
dokunewon 6:3a337a5e5aa7 226 printf("Switched to LINE-IN\n");
dokunewon 6:3a337a5e5aa7 227 InModeUSB = 0;
dokunewon 6:3a337a5e5aa7 228 }
dokunewon 6:3a337a5e5aa7 229 }
dokunewon 6:3a337a5e5aa7 230 //if now switched to LINE_INPUT mode
dokunewon 6:3a337a5e5aa7 231 else
dokunewon 6:3a337a5e5aa7 232 {
dokunewon 6:3a337a5e5aa7 233 //if USB_INPUT is attached
dokunewon 6:3a337a5e5aa7 234 if(USB_Audio_Attached)
dokunewon 6:3a337a5e5aa7 235 {
dokunewon 6:3a337a5e5aa7 236 //select USB_INPUT for input
dokunewon 6:3a337a5e5aa7 237 printf("Switched to USB-IN\n");
dokunewon 6:3a337a5e5aa7 238 InModeUSB = 1;
dokunewon 6:3a337a5e5aa7 239 }
dokunewon 6:3a337a5e5aa7 240 }
dokunewon 6:3a337a5e5aa7 241 //
dokunewon 6:3a337a5e5aa7 242 // RECEIVING AUDIO DATA
dokunewon 6:3a337a5e5aa7 243 //
dokunewon 6:3a337a5e5aa7 244 //show now in receive
dokunewon 6:3a337a5e5aa7 245 if(! Bank) LedR = 1;
dokunewon 6:3a337a5e5aa7 246 //if using USB-INPUT
dokunewon 6:3a337a5e5aa7 247 if(InModeUSB)
dokunewon 6:3a337a5e5aa7 248 {
dokunewon 6:3a337a5e5aa7 249 //receive USB-IN
dokunewon 6:3a337a5e5aa7 250 rc = usbdevice_receive32k(&audio,(uint32_t *)BufR[Bank]);
dokunewon 6:3a337a5e5aa7 251 }
dokunewon 6:3a337a5e5aa7 252 //if using LINE-IN
dokunewon 6:3a337a5e5aa7 253 else
dokunewon 6:3a337a5e5aa7 254 {
dokunewon 6:3a337a5e5aa7 255 //receive LINE-IN
dokunewon 6:3a337a5e5aa7 256 rc = usbdac.receive((uint8_t *)(BufR[Bank]), IN_DWORDS * 4);
dokunewon 6:3a337a5e5aa7 257 }
dokunewon 6:3a337a5e5aa7 258 //receiving ends
dokunewon 6:3a337a5e5aa7 259 LedR = 0;
dokunewon 6:3a337a5e5aa7 260 //
dokunewon 6:3a337a5e5aa7 261 // ERROR HANDLING and ALLOWING INPUT BUFFER
dokunewon 6:3a337a5e5aa7 262 //
dokunewon 6:3a337a5e5aa7 263 //if error occurs
dokunewon 6:3a337a5e5aa7 264 if(! rc)
dokunewon 6:3a337a5e5aa7 265 {
dokunewon 9:2ecebace33b1 266 //order send task to full some data to prevent data short
dokunewon 9:2ecebace33b1 267 //Recover = 1;
dokunewon 6:3a337a5e5aa7 268 //clear all buffers to mute
dokunewon 6:3a337a5e5aa7 269 audio.clear32k();
dokunewon 6:3a337a5e5aa7 270 FLT_Clear();
dokunewon 6:3a337a5e5aa7 271 memset((uint8_t *)BufR,0,IN_DWORDS * IN_BANKS * 4);
dokunewon 6:3a337a5e5aa7 272 memset((uint8_t *)BufW,0,OUT_DWORDS * OUT_BANKS * 4);
dokunewon 6:3a337a5e5aa7 273 }
dokunewon 6:3a337a5e5aa7 274 //if read correctly
dokunewon 6:3a337a5e5aa7 275 else
dokunewon 6:3a337a5e5aa7 276 {
dokunewon 6:3a337a5e5aa7 277 //allow to use read buffer for FFT task
dokunewon 6:3a337a5e5aa7 278 if(! Bank)
dokunewon 6:3a337a5e5aa7 279 {
dokunewon 6:3a337a5e5aa7 280 semR0.release();
dokunewon 6:3a337a5e5aa7 281 }
dokunewon 6:3a337a5e5aa7 282 else
dokunewon 6:3a337a5e5aa7 283 {
dokunewon 6:3a337a5e5aa7 284 semR1.release();
dokunewon 6:3a337a5e5aa7 285 }
dokunewon 6:3a337a5e5aa7 286 //select next bank
dokunewon 6:3a337a5e5aa7 287 Bank++;
dokunewon 6:3a337a5e5aa7 288 Bank &= 1;
dokunewon 6:3a337a5e5aa7 289 }
dokunewon 4:1e3019bcd565 290 }
dokunewon 4:1e3019bcd565 291 }