На вход звуковой карты на канал R и L поступают два аудио сигнала. Нужно сдвинуть канал L относительно R на 90 градусов, Как это проще реализовать ? Наверное можно R сдвинуть +45, а L -45 ... , если использовать FIR фильтр как рассчитать угол сдвига ??
Ок, программу сделал, кой как, как получать сэмплы с звуковой карты ?? Предварительно установив частоту дискретизации 1200 Гц ???????????
Andrei, доков и примеров (особенно с WinAPI и DirectSound) в инете теува хуча. А если попроще хочется, можно и BASS использовать или ещё какие-то библиотеки...
Пока плюнул, сделал на AVR, там хоть понятно с ADC напрямую можно читать семплы, все ворованное, фильтры с WinFilter, алгоритм с нета, ...., да и не факт что работает, отлаживать пока не получается, макетку собрать нужно ... ... Код (C++): #include <math.h> #include <util/delay.h> #include <avr/io.h> #include <avr/interrupt.h> #define Ntap 31 #define DCgain 32768 #define ADC_VREF_TYPE ((1<<REFS1) | (1<<REFS0) | (0<<ADLAR)) // Внутренне опорное напряжение 2,56 Вольта #define LED_PORT PORTC #define Led_I 1 #define Led_Q 2 #define Led_Run 0 // Глобальные переменные int OutSample,I,Q,N,X1,X2,X3,Y1,Y2,Y3; float count=0; int led_flag=0; int cos_N[4]={1,0,-1,0}; int sin_N[4]={0,1,0,-1}; int sin_N_m[4]={0,-1,0,1}; // Читаем ADC int read_adc(unsigned char adc_input) { ADMUX=adc_input | ADC_VREF_TYPE; // Delay needed for the stabilization of the ADC input voltage _delay_us(10); // Start the AD conversion ADCSRA|=(1<<ADSC); // Wait for the AD conversion to complete while ((ADCSRA & (1<<ADIF))==0); ADCSRA|=(1<<ADIF); return ADCW-512; // Убираем постоянную составляющую (преобразуем однополярный сигнал в двухполярный) } // Инициализация ADC void adc_init(void) { DIDR0=(0<<ADC7D) | (0<<ADC6D) | (0<<ADC5D) | (0<<ADC4D) | (0<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (0<<ADC0D); ADMUX=ADC_VREF_TYPE; ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (1<<ADPS0); ADCSRB=(0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0); } // Настройка генератора void clk_init(void) { CLKPR=(1<<CLKPCE); CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0); } // Инициализация портов void port_init(void) { // Порт А на ввод ADC (подтягивающие резисторы не включены) PORTA=0x00; DDRA=0x00; // Порт С на вывод PORTC=0x00; DDRC=0xFF; // Порт D на вывод PORTD=0x00; DDRD=0xFF; } // Настройки таймера 1 (Срабатывание по совпадению) void timer_init(void) { // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: 312,500 kHz // Mode: Normal top=0xFFFF // OC1A output: Disconnected // OC1B output: Disconnected // Noise Canceler: Off // Input Capture on Falling Edge // Timer Period: 0,20972 s // Timer1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: On // Compare B Match Interrupt: Off TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10); TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (1<<CS10); TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x01; OCR1AL=0x77; OCR1BH=0x00; OCR1BL=0x00; // Включение прерываний по таймеру TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (1<<OCIE1A) | (0<<TOIE1); } // Фильтр канала I int fir_I(int NewSample) { int FIRCoef[Ntap] = { -406, -207, 529, 240, -698, -274, 942, 308, -1317, -338, 1972, 363, -3441, -379, 10572, 17042, 10572, -379, -3441, 363, 1972, -338, -1317, 308, 942, -274, -698, 240, 529, -207, -406 }; static int x[Ntap]; //input samples long int y=0; //output sample int n; //shift the old samples for(n=Ntap-1; n>0; n--) x[n] = x[n-1]; //Calculate the new output x[0] = NewSample; for(n=0; n<Ntap; n++) y += FIRCoef[n] * x[n]; return y / DCgain; } // Фильтр канала Q int fir_Q(int NewSample) { int FIRCoef[Ntap] = { -406, -207, 529, 240, -698, -274, 942, 308, -1317, -338, 1972, 363, -3441, -379, 10572, 17042, 10572, -379, -3441, 363, 1972, -338, -1317, 308, 942, -274, -698, 240, 529, -207, -406 }; static int x[Ntap]; //input samples long int y=0; //output sample int n; //shift the old samples for(n=Ntap-1; n>0; n--) x[n] = x[n-1]; //Calculate the new output x[0] = NewSample; for(n=0; n<Ntap; n++) y += FIRCoef[n] * x[n]; return y / DCgain; } // Обработчик прерывания по таймеру 1200 Гц ISR (TIMER1_COMPA_vect) { if (N==3) { N=0; } else N++; I=read_adc(0); Q=read_adc(1); X1=I*cos_N[N]+Q*sin_N[N]; X2=fir_I(X1); X3=X2*cos_N[N]; Y1=I*sin_N_m[N]+Q*cos_N[N]; Y2=fir_Q(Y1); Y3=Y2*sin_N_m[N]; OutSample=X3+Y3; PORTD=OutSample+512;// восстанавливаем однополярный сигнал } int main (void) { //Инициализация ADC adc_init(); //Инициализация генератора clk_init(); // Инициализация портов port_init(); // Инициализация таймера timer_init(); // Разрешение прерываний sei(); while(1) { // Led_Run индикатор просчета фильтров if (count==1000) { led_flag=1; } else { count++; } if (led_flag==1) { LED_PORT |= 1 << Led_Run; //зажечь led_flag=0; count=0; } else { LED_PORT &= ~(1 << Led_I);// Гасим } if (I==0) { // Зажигаем диод I LED_PORT |= 1 << Led_I; //зажечь } else { // Гасим диод I LED_PORT &= ~(1 << Led_I);// Гасим } if (Q==0) { // Зажигаем диод Q LED_PORT |= 1 << Led_Q; //зажечь } else { // Гасим диод Q LED_PORT &= ~(1 << Led_I);// Гасим } } }