DWORD CBassAudio::GetLevelData ( void ) { if ( m_pSound ) { DWORD dwData = BASS_ChannelGetLevel ( m_pSound ); if ( dwData != 0 ) return dwData; } return 0; }
// scan the peaks void __cdecl ScanPeaks(DWORD decoder) { DWORD cpos=0,peak[2]={0}; while (!killscan) { DWORD level=BASS_ChannelGetLevel(decoder); // scan peaks DWORD pos; if (peak[0]<LOWORD(level)) peak[0]=LOWORD(level); // set left peak if (peak[1]<HIWORD(level)) peak[1]=HIWORD(level); // set right peak if (!BASS_ChannelIsActive(decoder)) pos=-1; // reached the end else pos=BASS_ChannelGetPosition(decoder,BASS_POS_BYTE)/bpp; if (pos>cpos) { DWORD a; for (a=0;a<peak[0]*(HEIGHT/2)/32768;a++) wavebuf[(HEIGHT/2-1-a)*WIDTH+cpos]=1+a; // draw left peak for (a=0;a<peak[1]*(HEIGHT/2)/32768;a++) wavebuf[(HEIGHT/2+1+a)*WIDTH+cpos]=1+a; // draw right peak if (pos>=WIDTH) break; // gone off end of display cpos=pos; peak[0]=peak[1]=0; } } BASS_StreamFree(decoder); // free the decoder scanthread=0; }
// update the spectrum display - the interesting bit :) void CALLBACK UpdateSpectrum(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { static DWORD quietcount=0; HDC dc; int x,y,y1; if (specmode==3) { // waveform short buf[SPECWIDTH]; memset(specbuf,0,SPECWIDTH*SPECHEIGHT); BASS_ChannelGetData(chan,buf,sizeof(buf)); // get the sample data for (x=0;x<SPECWIDTH;x++) { int v=(32767-buf[x])*SPECHEIGHT/65536; // invert and scale to fit display if (!x) y=v; do { // draw line from previous sample... if (y<v) y++; else if (y>v) y--; specbuf[y*SPECWIDTH+x]=abs(y-SPECHEIGHT/2)*2+1; } while (y!=v); } } else { float fft[1024]; BASS_ChannelGetData(chan,fft,BASS_DATA_FFT2048); // get the FFT data if (!specmode) { // "normal" FFT memset(specbuf,0,SPECWIDTH*SPECHEIGHT); for (x=0;x<SPECWIDTH/2;x++) { #if 1 y=sqrt(fft[x+1])*3*SPECHEIGHT-4; // scale it (sqrt to make low values more visible) #else y=fft[x+1]*10*SPECHEIGHT; // scale it (linearly) #endif if (y>SPECHEIGHT) y=SPECHEIGHT; // cap it if (x && (y1=(y+y1)/2)) // interpolate from previous to make the display smoother while (--y1>=0) specbuf[y1*SPECWIDTH+x*2-1]=y1+1; y1=y; while (--y>=0) specbuf[y*SPECWIDTH+x*2]=y+1; // draw level } } else if (specmode==1) { // logarithmic, acumulate & average bins int b0=0; memset(specbuf,0,SPECWIDTH*SPECHEIGHT); #define BANDS 28 for (x=0;x<BANDS;x++) { float peak=0; int b1=pow(2,x*10.0/(BANDS-1)); if (b1>1023) b1=1023; if (b1<=b0) b1=b0+1; // make sure it uses at least 1 FFT bin for (;b0<b1;b0++) if (peak<fft[1+b0]) peak=fft[1+b0]; y=sqrt(peak)*3*SPECHEIGHT-4; // scale it (sqrt to make low values more visible) if (y>SPECHEIGHT) y=SPECHEIGHT; // cap it while (--y>=0) memset(specbuf+y*SPECWIDTH+x*(SPECWIDTH/BANDS),y+1,0.9*(SPECWIDTH/BANDS)); // draw bar } } else { // "3D" for (x=0;x<SPECHEIGHT;x++) { y=sqrt(fft[x+1])*3*127; // scale it (sqrt to make low values more visible) if (y>127) y=127; // cap it specbuf[x*SPECWIDTH+specpos]=128+y; // plot it } // move marker onto next position specpos=(specpos+1)%SPECWIDTH; for (x=0;x<SPECHEIGHT;x++) specbuf[x*SPECWIDTH+specpos]=255; } } // update the display dc=GetDC(win); BitBlt(dc,0,0,SPECWIDTH,SPECHEIGHT,specdc,0,0,SRCCOPY); if (LOWORD(BASS_ChannelGetLevel(chan))<500) { // check if it's quiet quietcount++; if (quietcount>40 && (quietcount&16)) { // it's been quiet for over a second RECT r={0,0,SPECWIDTH,SPECHEIGHT}; SetTextColor(dc,0xffffff); SetBkMode(dc,TRANSPARENT); DrawText(dc,"make some noise!",-1,&r,DT_CENTER|DT_VCENTER|DT_SINGLELINE); } } else quietcount=0; // not quiet ReleaseDC(win,dc); }
//----------------------------------------------------------------------------- void LLFFTSound::update(float addedTime) { if(!m_bInitialized || !m_bPlaying) return; #ifdef _WINDOWS // update current waveform level #if BASSVERSION == 0x204 DWORD pos = BASS_ChannelGetPosition(m_dChannel, BASS_POS_BYTE); if (pos == BASS_ChannelGetLength(m_dChannel, BASS_POS_BYTE)) #else DWORD pos = BASS_ChannelGetPosition(m_dChannel); if (pos == BASS_ChannelGetLength(m_dChannel)) #endif { m_fCurrLevelLeft = 0.0f; m_fCurrLevelRight = 0.0f; m_bPlaying = false; BASS_ChannelStop(m_dChannel); // reset bands values for (int i=0; i< BANDS; i++) m_fBands[i] = 0.0f; // reset events queue resetEvent(); } else { // update lever for each channel DWORD level = BASS_ChannelGetLevel(m_dChannel); m_fCurrLevelLeft = ((double)LOWORD(level) / 32768); // range 0 to 1: left channel is low word m_fCurrLevelRight = ((double)HIWORD(level) / 32768); // range 0 to 1: right channel is high word // update band spectrum float fft[1024]; BASS_ChannelGetData(m_dChannel,fft,BASS_DATA_FFT2048); // get the FFT data int b0=0; int x,y; #define FFTCAP 256.0f for (x=0; x<BANDS; x++) { float sum=0; int sc,b1 = pow(2,x*10.0/(BANDS-1)); if (b1>1023) b1=1023; if (b1<=b0) b1=b0+1; // make sure it uses at least 1 FFT bin sc = 10 + b1 - b0; for (;b0<b1;b0++) sum+=fft[1+b0]; y=(sqrt(sum/log10((double)sc))*1.7*FFTCAP)-4; // scale it if (y>FFTCAP) y=FFTCAP; // cap it // store band value m_fBands[x] = y; m_fBands[x] /= FFTCAP; // normalized band value (0.0 - 1.0) } // check event associated with this sound file: use pos variable to detect timing... float elapsedTime = BASS_ChannelBytes2Seconds(m_dChannel,pos); if (m_iNumEvents && !m_bEventDone) { if (elapsedTime > 0.0f) { // there is possibility that multiple events have the same timestamp... // should do some kind of iteration. bool running = true; while(running) { if (m_fNextEventTime < elapsedTime) { // execute callback function i_CharacterEventCallback.execute(m_vEventVec[m_iNextEvent]); // move to next event m_iNextEvent++; if (m_iNextEvent == m_iNumEvents) { // reached the last event m_iNextEvent = 0; m_bEventDone = true; running = false; } m_fNextEventTime = m_vEventVec[m_iNextEvent]->eTime; } else running = false; } } } } #endif }
DWORD bmx_bass_channelgetlevel(DWORD handle, DWORD * left, DWORD * right) { DWORD level = BASS_ChannelGetLevel(handle); *left = LOWORD(level); *right = HIWORD(level); return level; }