Это - достаточно беспорядочный архив сообщений конференций сети fidonet, которые на момент их прочтения мной
показались полезными или интересными. Многие устарели, многие узкоспецифичны и малоинтересны, но может оказаться и что-то новое...
- __techs (2:5015/42) ----------------------------------------------- __techs - Msg : 462 of 1000 Scn From : Vadim Radionov 2:4616/8.8 14 Aug 97 17:36:20 To : Sergey Trapeznikov 16 Aug 97 15:32:54 Subj : Re: Fast Fourier Transform ------------------------------------------------------------------------------- @AREA:NICE.SOURCES @ Скопиpовано из области 'NICE.SOURCES' @ Скопиpовано из области 'NETMAIL' Здравствуйте, Sergey! ■ Quoting message from Sergey Trapeznikov to All ■ [12 Aug 97 at 21:22] ST> У меня имеются данные, соответствующие оцифpованному звуку. Хотелось бы в ST> pеальном вpемени пpоизводить pазложение в частотный спектp. ST> Иначе говоpя хочется написать частотный индикатоp для пpоги, котоpая ST> пpигpывает звуки. Если у кого-либо есть какая-нибудь инфа по этому поводу, ST> то я pад буду ее почитать. Любые исходники пpиветствуются. Могу предложить альтернативу: не FFT использовать, а быстрое преобразованние Уолша. В нем применяется целочисленная арифметика. Вот кусок из программы: ---- Cut ---- //------------------------------------------------------------------------ // Файл fwt.cpp // Автор: Радионов В. // Hазначение: Управление цветомузыкой // Примечание: текст написан для Watcom C++, работает только в модели FLAT //------------------------------------------------------------------------ unsigned short BinInvCode( unsigned short n ) { unsigned short mask=0x80,r=0; for( int i=0; i<8; i++, mask>>=1,n>>=1 ) if( n & 1 ) r|=mask; return r; } unsigned UnGray( unsigned short n ) { unsigned short mask=0x80,r=n; int s=0; for( int i=0; i<8; i++, mask>>=1 ) { if( s ) r^=mask; if( n & mask ) s^=1; } return r; } unsigned short h2w( unsigned short n ) { return( UnGray( BinInvCode( n ) ) ); } void reorder( short *a, int ) { static short a1[256]; for( int i=0; i< 256; i++ ) { a1[h2w(i)]=a[i]; } for( i=0;i< 256; i++ ) a[i]=a1[i]; } static int doReorder = 1; extern "C" void cdecl toggleReorder(); void cdecl toggleReorder() { doReorder = !doReorder; } // Быстрое Уолш преобразование const short n = 256; const short r = 8; short Frame[ n + 80 ]; // Kадр, сыгранный только что. extern "C" void __cdecl FWT( short * ); extern "C" void __cdecl drawSpectrum(); void __cdecl FWT( short *v0 ) { short *v1 = Frame; int n2=n/2; for( int j=1; j<=r; j++ ) { for( int i=0; i<n2; i++ ) { v1[i]=v0[2*i]+v0[2*i+1]; v1[i+n2]=v0[2*i]-v0[2*i+1]; } short *tmp=v0; v0=v1; v1=tmp; // swap( v0,v1); } // Reorder if( doReorder ) reorder( v0, n ); // if( !( r&1 ) ) for( int i=0; i< n;i++ ) v1[i]=v0[i]>>=6; } short mod( short arg ); #pragma aux mod = \\ "test ax, 8000h" \\ "jz Skip" \\ "neg ax" \\ "Skip:" \\ parm [ax] \\ value [ ax ]; int startPos = 0; extern "C" void cdecl shiftPos(); void cdecl shiftPos() { if( startPos + 80 < 256 ) startPos += 80; else startPos = 0; } void __cdecl drawSpectrum() { char *video=(char *)0xb8000; for( int y=0; y<25; y++) for( int x=0; x<80; x++,video+=2 ) if( ( mod(Frame[startPos + x])/ 2 ) > (25-y) ) { *video='█'; video[1]=3; } else *video=' '; } extern "C" void cdecl _init_video(); //extern "C" void cdecl _done_video(); extern "C" void _bar( short x0, short y0, short x1, short y1, short color ); void setpal(char color,char R,char G, char B); #pragma aux setpal = \\ "mov dx,0x3C8" \\ "mov al,bh" \\ "out dx,al" \\ "inc dx" \\ "mov al,bl" \\ "out dx,al" \\ "mov al,ch" \\ "out dx,al" \\ "mov al,cl" \\ "out dx,al" \\ parm [bh] [bl] [ch] [cl]; void cdecl _init_video() { // #pragma aux _init_video = \\ // "mov ax, 000Dh " \\ // "int 10h"; setpal( 16, 30, 00, 0 ); setpal( 17, 30, 30, 0 ); setpal( 18, 0, 0, 30 ); } void _done_video() { #pragma aux _done_video = \\ "mov ax, 0003h " \\ "int 10h"; } void _bar( short x0, short y0, short x1, short y1, short color ) { char *video = ( char *)0xA0000 + y0*320 + x0; short width = x1 - x0; for( short y = y0; y <= y1; y++ ) { for( short c = width; c; c-- ) *video++ = color; video += 320 - width; } } extern "C" void cdecl draw_bars(); void cdecl draw_bars() { _bar( 50, 50, 100, 100, 16 ); _bar( 150, 50, 200, 100, 17 ); _bar( 250, 50, 300, 100, 18 ); } extern "C" void cdecl control_bars( short l1, short l2, short l3 ); void cdecl control_bars( short l1, short l2, short l3 ) { static short _l1 = 0, _l2 = 0, _l3 = 0; static short b1 = 0, b2 = 0, b3 = 0; l1 = mod( l1 ); l2 = mod( l2 ); l3 = mod( l3 ); if( l1 > _l1 ) _l1 = l1; // _l1++; if( l2 > _l2 ) _l2 = l2; // _l2++; if( l3 > _l3 ) _l3 = l3; // _l3++; if( l1 < _l1 ) _l1--; if( l2 < _l2 ) _l2--; if( l3 < _l3 ) _l3--; if( l1 != _l1 ) setpal( 16, _l1 * 2, 0, 0 ); if( l2 != _l2 ) setpal( 17, _l2 * 2, _l2 * 2, 0 ); if( l3 != _l3 ) setpal( 18, 0 , 0, _l3 * 2 ); } ---- Сut ---- K сожалению ( или к счастью ), это единственный модуль на С++, главная же процедура спектрального анализа написана на asm: ;---------------------------------- ; Спектральный анализ ;---------------------------------- proc doSpectrum cmp [ FrameReady ], 0 je end_spec mov eax, offset Frame call CopyFrame mov eax, offset Frame push eax call _FWT pop eax call _drawSpectrum movzx eax, [ word Frame + 40 ] push eax movzx eax, [ word Frame + 20 ] push eax movzx eax, [ word Frame + 2 ] push eax call _control_bars add esp, 12 ; call delay mov [ FrameReady ], 0 end_spec: ret endp С наилучшими пожеланиями - Вадим. --- TM-Ed 1.14+ * Origin: ->> TM-Ed default Origin <<- (2:4616/8.8)