BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user) { DWORD bl; BASS_StreamPutData(chan,buffer,length); // feed recorded data to output stream bl=BASS_ChannelGetData(chan,NULL,BASS_DATA_AVAILABLE); // get output buffer level if (prebuf) { // prebuffering if (bl>=prebuf+length) { // gone 1 block past the prebuffering target #ifdef ADJUSTRATE targbuf=bl; // target the current level prevbuf=0; #endif prebuf=0; // finished prebuffering BASS_ChannelPlay(chan,FALSE); // start the output } } else { // playing #ifdef ADJUSTRATE if (bl<targbuf) { // buffer level is below target, slow down... rate--; BASS_ChannelSetAttribute(chan,BASS_ATTRIB_FREQ,rate); prevbuf=0; } else if (bl>targbuf && bl>=prevbuf) { // buffer level is high and not falling, speed up... rate++; BASS_ChannelSetAttribute(chan,BASS_ATTRIB_FREQ,rate); prevbuf=bl; } #endif } return TRUE; // continue recording }
/** * @brief No incoming parameters. Get data from RCHAN. Creating the stream file. If BASS_StreamCreateFile is failure colled BASS_Free(). * @param No params */ void Widget::stopRecording() { if (BASS_ChannelGetData(rchan, this->fft, BASS_DATA_FFT1024 | BASS_DATA_FFT_COMPLEX) == -1) { QDEBUG("Cannot get recbuf from rchan"); QDEBUG(BASS_ErrorGetCode()); } BASS_ChannelStop(rchan); rchan=0; ui->pushButton->setText(tr("Record")); // complete the WAVE header *(DWORD*)(recbuf+4)=reclen-8; *(DWORD*)(recbuf+40)=reclen-44; // enable "save" button ui->pushButton_3->setEnabled(true); // setup output device (using default device) if (!BASS_Init(-1,44100,0,NULL,NULL)) { QDEBUG(BASS_ErrorGetCode()); QDEBUG("Can't initialize output device"); return; } // create a stream from the recording if (chan=BASS_StreamCreateFile(TRUE,recbuf,0,reclen,BASS_SAMPLE_FLOAT)) { //ui->pushButton_2->setEnabled(true); // enable "play" button } else BASS_Free(); ui->pushButton->setEnabled(true); }
void Player::push(void *data, uint32_t size) { int buffered = BASS_ChannelGetData(_output, NULL, BASS_DATA_AVAILABLE); Log::msg("In buffer: %d - New: %d", buffered, size); if(BASS_StreamPutData(_output, data, size) == (DWORD)-1) Log::error("Bass Error: putting stream data failed: %s", GetBassStrError()); }
bool BassPlayer::calcSpectrum(QList<QVector<float> > & result) { float fft[1024 * channels_count]; BASS_ChannelGetData(chan, fft, BASS_DATA_FFT2048 | BASS_DATA_FFT_INDIVIDUAL | BASS_DATA_FFT_REMOVEDC); QVector<float> peaks; int b0 = 0, x, z, peakNum; for (x = 0; x < channels_count; x++) result.append(QVector<float>()); for (x = 0; x < calcSpectrumBandsGroupCount(); x++) { peaks.fill(0, channels_count); int b1 = spectrumComplexPoints[x]; for (; b0 < b1; b0++) { peakNum = b0 % channels_count; if (peaks[peakNum] < fft[b0]) peaks[peakNum] = fft[b0]; } for (z = 0; z < channels_count; z++) result[z].append(sqrt(peaks[z])); } return true; }
bool PlaybackWidget::getFFT(void *buffer) { if(state == PLAYING && BASS_ChannelGetData(curchan, buffer, BASS_DATA_FFT8192) >= 0) return true; return false; }
float* CBassAudio::GetFFTData ( int iLength ) { if ( m_pSound ) { long lFlags = BASS_DATA_FFT256; if ( iLength == 256 ) lFlags = BASS_DATA_FFT256; else if ( iLength == 512 ) lFlags = BASS_DATA_FFT512; else if ( iLength == 1024 ) lFlags = BASS_DATA_FFT1024; else if ( iLength == 2048 ) lFlags = BASS_DATA_FFT2048; else if ( iLength == 4096 ) lFlags = BASS_DATA_FFT4096; else if ( iLength == 8192 ) lFlags = BASS_DATA_FFT8192; else if ( iLength == 16384 ) lFlags = BASS_DATA_FFT16384; else return NULL; float* pData = new float[ iLength ]; if ( BASS_ChannelGetData ( m_pSound, pData, lFlags ) != -1 ) return pData; else { delete [] pData; return NULL; } } return NULL; }
void render::updateSounds() { float buffer[1024 * 4]; BASS_ChannelGetData(sound_chan, buffer, -2147483645); num = 0.0f; for (int i = 0; i <= 15; i++) num += buffer[i]; num *= (13.0f/15.0f); }
/* check that buffer has sufficient decoded data */ void CheckBuffer(BUFSTUFF *b, DWORD pos) { if (pos>b->writepos) { int o=min(b->readposl,b->readposr); b->writepos-=o; memmove(b->buf,b->buf+o*2,b->writepos*4); // shift over used data b->readposl-=o; b->readposr-=o; pos-=o; // read upto requested position b->writepos+=BASS_ChannelGetData(b->dstr,b->buf+b->writepos*2,(pos-b->writepos)*4)/4; } }
static BOOL Initialize() { BASS_INFO bi; // initialize output, get latency if (!BASS_Init(-1,44100,BASS_DEVICE_LATENCY,win,NULL)) { Error("Can't initialize output"); return FALSE; } BASS_GetInfo(&bi); if (bi.dsver<8) { // no DX8, so disable effect buttons EnableWindow(GetDlgItem(win,20),FALSE); EnableWindow(GetDlgItem(win,21),FALSE); EnableWindow(GetDlgItem(win,22),FALSE); EnableWindow(GetDlgItem(win,23),FALSE); } // create a stream to play the recording chan=BASS_StreamCreate(44100,2,0,STREAMPROC_PUSH,0); // start recording with 10ms period if (!BASS_RecordInit(-1) || !(rchan=BASS_RecordStart(44100,2,MAKELONG(0,10),RecordingCallback,0))) { BASS_RecordFree(); BASS_Free(); Error("Can't initialize recording"); return FALSE; } { // get list of inputs int c; const char *i; for (c=0;i=BASS_RecordGetInputName(c);c++) { float level; MESS(10,CB_ADDSTRING,0,i); if (!(BASS_RecordGetInput(c,&level)&BASS_INPUT_OFF)) { // this 1 is currently "on" input=c; MESS(10,CB_SETCURSEL,input,0); MESS(11,TBM_SETPOS,TRUE,level*100); // set level slider } } } { // prebuffer at least "minbuf" amount of data before starting playback DWORD prebuf=BASS_ChannelSeconds2Bytes(chan,bi.minbuf/1000.f); while (BASS_ChannelGetData(chan,NULL,BASS_DATA_AVAILABLE)<prebuf) Sleep(1); } BASS_ChannelPlay(chan,FALSE); return TRUE; }
unsigned int BassDecoder::fetch(Signal& left, Signal& right){ if (_music) { DWORD readed=0; #if defined(LIBTOOLS_WINDOWS) && !defined(BASS_H) if (!BASS_ChannelGetData || ! BASS_ErrorGetCode) { std::cerr << "Error missing BASS_ChannelGetData or BASS_ErrorGetCode functions" << std::endl; return 0; } #endif readed=BASS_ChannelGetData((DWORD)_music, (void*)_samplesForSignals, _bytesFrame); if(readed==-1 && BASS_ErrorGetCode() == BASS_ERROR_ENDED) { left.reset(); right.reset(); _ended=true; return 0; } if (readed < _bytesFrame) { for (unsigned int i=readed; i< _bytesFrame ;i++) ((char*)_samplesForSignals)[i]=0; } const unsigned int signal_size=Signal::size; if (_infos.chans>=2) { unsigned int k=0; for (unsigned int i=0; i < signal_size;) { left.samples[i]=_samplesForSignals[k++]; right.samples[i++]=_samplesForSignals[k++]; k+=_infos.chans-2; } } else if (_infos.chans==1) //mono { unsigned int k=0; for (unsigned int i=0; i < signal_size;) { left.samples[i]=_samplesForSignals[k]; right.samples[i++]=_samplesForSignals[k++]; } } return readed/sizeof(sample); } return 0; }
HEFFECT CALL HGE_Impl::Effect_Load(const char *filename, DWORD size) { DWORD _size, length, samples; HSAMPLE hs; HSTREAM hstrm; BASS_CHANNELINFO info; void *buffer, *data; if(hBass) { if(bSilent) return 1; if(size) { data=(void *)filename; _size=size; } else { data=Resource_Load(filename, &_size); if(!data) return NULL; } hs=BASS_SampleLoad(TRUE, data, 0, _size, 4, BASS_SAMPLE_OVER_VOL); if(!hs) { hstrm=BASS_StreamCreateFile(TRUE, data, 0, _size, BASS_STREAM_DECODE); if(hstrm) { length=(DWORD)BASS_ChannelGetLength(hstrm); BASS_ChannelGetInfo(hstrm, &info); samples=length; if(info.chans < 2) samples>>=1; if((info.flags & BASS_SAMPLE_8BITS) == 0) samples>>=1; buffer=BASS_SampleCreate(samples, info.freq, 2, 4, info.flags | BASS_SAMPLE_OVER_VOL); if(!buffer) { BASS_StreamFree(hstrm); _PostError("Can't create sound effect: Not enough memory"); } else { BASS_ChannelGetData(hstrm, buffer, length); hs=BASS_SampleCreateDone(); BASS_StreamFree(hstrm); if(!hs) _PostError("Can't create sound effect"); } } } if(!size) Resource_Free(data); return hs; }
bool BassPlayer::calcSpectrum(QVector<float> & result) { int b0 = 0; float fft[1024]; BASS_ChannelGetData(chan, fft, BASS_DATA_FFT2048); for (int x = 0; x < sbands_count; x++) { float peak = 0; int b1 = spectrumPoints[x]; for (; b0 < b1; b0++) if (peak < fft[1 + b0]) peak = fft[1 + b0]; result.append(sqrt(peak)); } return true; }
// Load an audio file in .wav format bool LoadAudioFile(LPCSTR szFileName) { // Load the data from the specified file HSTREAM file_stream = BASS_StreamCreateFile(FALSE,szFileName,0,0,BASS_STREAM_DECODE); // Get the length and header info from the loaded file stream_length=BASS_StreamGetLength(file_stream); BASS_ChannelGetInfo(file_stream, &info); // Get the audio samples from the loaded file data = new char[(unsigned int)stream_length]; BASS_ChannelGetData(file_stream, data, (unsigned int)stream_length); // Set playing to begin at the beginning of the loaded data pos = 0; return false; }
//--------------------------------------------------------------------------- // buffer the recorded data BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user) { // increase buffer size if needed if ((reclen%BUFSTEP)+length>=BUFSTEP) { recbuf=(char *)realloc((char *)recbuf,((reclen+length)/BUFSTEP+1)*BUFSTEP); if (!recbuf) { rchan=0; //Error("Out of memory!"); //MESS(10,WM_SETTEXT,0,"Record"); return FALSE; // stop recording } } // buffer the data memcpy(recbuf+reclen,buffer,length); reclen+=length; int res=BASS_ChannelGetData(rchan,buf,BASS_DATA_FFT16384|BASS_DATA_FLOAT); // get the sample data (floating-point to avoid 8 & 16 bit processing) return TRUE; // continue recording }
// // Util use in BeginLoadingMedia // HSTREAM CBassAudio::ConvertFileToMono(const SString& strPath) { HSTREAM decoder = BASS_StreamCreateFile ( false, strPath, 0, 0, BASS_STREAM_DECODE | BASS_SAMPLE_MONO ); // open file for decoding if ( !decoder ) return 0; // failed DWORD length = static_cast <DWORD> ( BASS_ChannelGetLength ( decoder, BASS_POS_BYTE ) ); // get the length void *data = malloc ( length ); // allocate buffer for decoded data BASS_CHANNELINFO ci; BASS_ChannelGetInfo ( decoder, &ci ); // get sample format if ( ci.chans > 1 ) // not mono, downmix... { HSTREAM mixer = BASS_Mixer_StreamCreate ( ci.freq, 1, BASS_STREAM_DECODE | BASS_MIXER_END ); // create mono mixer BASS_Mixer_StreamAddChannel ( mixer, decoder, BASS_MIXER_DOWNMIX | BASS_MIXER_NORAMPIN | BASS_STREAM_AUTOFREE ); // plug-in the decoder (auto-free with the mixer) decoder = mixer; // decode from the mixer } length = BASS_ChannelGetData ( decoder, data, length ); // decode data BASS_StreamFree ( decoder ); // free the decoder/mixer HSTREAM stream = BASS_StreamCreate ( ci.freq, 1, BASS_STREAM_AUTOFREE, STREAMPROC_PUSH, NULL ); // create stream BASS_StreamPutData ( stream, data, length ); // set the stream data free ( data ); // free the buffer return stream; }
float* CBassAudio::GetWaveData ( int iLength ) { if ( m_pSound ) { long lFlags = 0; if ( iLength == 128 || iLength == 256 || iLength == 512 || iLength == 1024 || iLength == 2048 || iLength == 4096 || iLength == 8192 || iLength == 16384 ) { lFlags = 4*iLength|BASS_DATA_FLOAT; } else return NULL; float* pData = new float [ iLength ]; if ( BASS_ChannelGetData ( m_pSound, pData, lFlags ) != -1 ) return pData; else { delete [] pData; return NULL; } } return NULL; }
void cSnd::Vpr() { // get data if (view.eVis==viPrint && surf && PlR) { EnterCriticalSection(&cs); BASS_ChannelGetData(bPlay ? chPl : chRec, fftB, fts[view.fftSize] ); for (int x=0; x < view.xSize+1; x++) { float f = fftB[x+1]; if (f<0.000001f) f=0.000001f; float y = -log10(f) * view.fftMul /255.f -0.1f; //par y = mia(0.f,1.0f, y); C[xpn][x] = 1.f-y; } // _ write pos xpr++; if (xpn < PrLin) xpn++; if (xpr >= view.xSize) xpr = 0; LeaveCriticalSection(&cs); }else if (!bPaused) { xpr = 0; xpn = 0; } }
void Vis::paintEvent(QPaintEvent *event){ if(!this->isVisible()){ return; } BASS_ChannelGetData(this->chan, fft, BASS_DATA_FFT8192); //получение даных БФП if(this->ctype == 1){ if(this->Draw){ QPainter paint(this); this->Draw(paint, fft); } else{ qDebug() << "error: cold not resolve Draw..."; } } else if(this->ctype == 2){ if(this->Upd){ this->Upd(fft); } else{ err << "could't resolve Update()"; } } memset(fft, 0, sizeof(this->fft)); }
// update the spectrum display - the interesting bit :) gboolean UpdateSpectrum(gpointer data) { int x,y,y1; RGB *specbuf=(RGB*)gdk_pixbuf_get_pixels(specpb); if (specmode==3) { // waveform int c; float *buf; BASS_CHANNELINFO ci; memset(specbuf,0,SPECWIDTH*SPECHEIGHT*sizeof(*specbuf)); BASS_ChannelGetInfo(chan,&ci); // get number of channels buf=alloca(ci.chans*SPECWIDTH*sizeof(float)); // allocate buffer for data BASS_ChannelGetData(chan,buf,(ci.chans*SPECWIDTH*sizeof(float))|BASS_DATA_FLOAT); // get the sample data (floating-point to avoid 8 & 16 bit processing) for (c=0;c<ci.chans;c++) { for (x=0;x<SPECWIDTH;x++) { int v=(1-buf[x*ci.chans+c])*SPECHEIGHT/2; // invert and scale to fit display if (v<0) v=0; else if (v>=SPECHEIGHT) v=SPECHEIGHT-1; if (!x) y=v; do { // draw line from previous sample... if (y<v) y++; else if (y>v) y--; specbuf[y*SPECWIDTH+x]=palette[c&1?127:1]; // left=green, right=red (could add more colours to palette for more chans) } 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*sizeof(*specbuf)); 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[(SPECHEIGHT-1-y1)*SPECWIDTH+x*2-1]=palette[y1+1]; y1=y; while (--y>=0) specbuf[(SPECHEIGHT-1-y)*SPECWIDTH+x*2]=palette[y+1]; // draw level } } else if (specmode==1) { // logarithmic, acumulate & average bins int b0=0; memset(specbuf,0,SPECWIDTH*SPECHEIGHT*sizeof(*specbuf)); #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) for (y1=0;y1<SPECWIDTH/BANDS-2;y1++) specbuf[(SPECHEIGHT-1-y)*SPECWIDTH+x*(SPECWIDTH/BANDS)+y1]=palette[y+1]; // 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[(SPECHEIGHT-1-x)*SPECWIDTH+specpos]=palette[128+y]; // plot it } // move marker onto next position specpos=(specpos+1)%SPECWIDTH; for (x=0;x<SPECHEIGHT;x++) specbuf[x*SPECWIDTH+specpos]=palette[255]; } } gtk_image_set_from_pixbuf(GTK_IMAGE(speci),specpb); // update the display return TRUE; }
// 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 net_radio_getFftData1024Floats(float* data) { BASS_ChannelGetData(chan, data, BASS_DATA_FFT2048); }
int decodeFunc(void* inData) { int a, b, r, g, i; //short waveData[8 * 1024]; unsigned int* fftPtr; unsigned int* fftOutput; float fftData[1024]; //double timeInSec = 0.0; const float maxIntensity = 500 * 2; const int COLOR_STEPS = 255; const int PALETTE_SIZE = 3 * COLOR_STEPS; const int spectrumLength = 1024; ThreadFuncData* threadData = (ThreadFuncData*)inData; unsigned int colors[255 * 3]; int imageHeight = 128; HSTREAM chan = threadData->stream; MusicData* data = threadData->data; float percentDone = 1.0f; float step = 0.0f; mtx_lock(&s_mutex); const int SAMPLING_FREQUENCY = 100; //warning: in TimelineImage this samplingfrequency is assumed to be 100 const double SAMPLING_RESOLUTION = 1.0 / SAMPLING_FREQUENCY; QWORD sampleLength = BASS_ChannelSeconds2Bytes(chan, SAMPLING_RESOLUTION); int numSamples = (int)((double)BASS_ChannelGetLength(chan, BASS_POS_BYTE) / (double)sampleLength); //printf("Num samples %d\n", (int)sampleLength); //printf("Num samples %d\n", numSamples); BASS_ChannelPlay(chan, 0); int j_table[128]; int pj_table[128]; int nj_table[128]; // TODO: Size optimize? data->sampleCount = numSamples; fftPtr = fftOutput = (unsigned int*)malloc(128 * 4 * (numSamples + 1)); //const int spectrumLength = 1024; //const int imageHeight = 256; //var spectrumImage = new Bitmap((int)numSamples, imageHeight); //var volumeImage = new Bitmap((int)numSamples, imageHeight); //s_editorData.waveViewSize = 128; //s_editorData.trackViewInfo.windowSizeX -= s_editorData.waveViewSize; //timeInSec =(DWORD)BASS_ChannelBytes2Seconds(chan, len); //printf(" %u:%02u\n", (int)timeInSec / 60, (int)timeInSec % 60); for (i = 0; i < PALETTE_SIZE; ++i) { a = 255; if (i < PALETTE_SIZE * 0.666f) a = (int)(i * 255 / (PALETTE_SIZE * 0.666f)); b = 0; if (i < PALETTE_SIZE * 0.333f) b = i; else if (i < PALETTE_SIZE * 0.666f) b = -i + 510; r = 0; if (i > PALETTE_SIZE * 0.666f) r = 255; else if (i > PALETTE_SIZE * 0.333f) r = i - 255; g = 0; if (i > PALETTE_SIZE * 0.666f) g = i - 510; colors[i] = Emgui_color32((uint8_t)r, (uint8_t)g, (uint8_t)b, (uint8_t)a); } float f = (float)(spectrumLength / log((float)(imageHeight + 1))); float f2 = (float)((PALETTE_SIZE - 1) / log(maxIntensity + 1)); (void)f2; for (int rowIndex = 0; rowIndex < imageHeight; ++rowIndex) { int j_ = (int)(f * log(rowIndex + 1)); int pj_ = (int)(rowIndex > 0 ? f * log(rowIndex - 1 + 1) : j_); int nj_ = (int)(rowIndex < imageHeight - 1 ? f * log(rowIndex + 1 + 1) : j_); j_table[rowIndex] = j_; pj_table[rowIndex] = pj_; nj_table[rowIndex] = nj_; } step = (float)(99.0f / numSamples); percentDone = 1.0f; for (int sampleIndex = 0; sampleIndex < numSamples; ++sampleIndex) { BASS_ChannelSetPosition(chan, sampleIndex * sampleLength, BASS_POS_BYTE); BASS_ChannelGetData(chan, fftData, BASS_DATA_FFT2048); data->percentDone = (int)(percentDone); //printf("%d/%d\n", sampleIndex, numSamples); for (int rowIndex = 0; rowIndex < imageHeight; ++rowIndex) { //int j_ = (int)(f * log(rowIndex + 1)); //int pj_ = (int)(rowIndex > 0 ? f * log(rowIndex - 1 + 1) : j_); //int nj_ = (int)(rowIndex < imageHeight - 1 ? f * log(rowIndex + 1 + 1) : j_); int j_ = j_table[(imageHeight - rowIndex) - 1]; int pj_ = pj_table[(imageHeight - rowIndex) - 1]; int nj_ = nj_table[(imageHeight - rowIndex) - 1]; //printf("index %d - %d %d %d\n", rowIndex, j_, pj_, nj_); float intensity = 125.0f * 4.0f * fftData[spectrumLength - pj_ - 1] + 750.0f * 4.0f * fftData[spectrumLength - j_ - 1] + 125.0f * 4.0f * fftData[spectrumLength - nj_ - 1]; if (intensity > maxIntensity) intensity = maxIntensity; if (intensity < 0.0f) intensity = 0.0f; int palettePos = (int)(f2 * log(intensity + 1)); *fftOutput++ = colors[palettePos]; } percentDone += step; } BASS_StreamFree(chan); free(threadData); data->percentDone = 100; data->fftData = fftPtr; mtx_unlock(&s_mutex); //printf("thread done\n"); return 1; }
/* Диалоговая процедура */ INT_PTR CALLBACK Application::DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { HANDLE_MSG(hWnd, WM_CTLCOLORSTATIC, _this->OnColorStatic); HANDLE_MSG(hWnd, WM_CTLCOLORDLG, _this->OnCtlColor); HANDLE_MSG(hWnd, WM_TIMER, _this->Cls_OnTimer); HANDLE_MSG(hWnd, WM_INITDIALOG, _this->Cls_OnInitDialog); HANDLE_MSG(hWnd, WM_HSCROLL, _this->Cls_OnHScroll); HANDLE_MSG(hWnd, WM_COMMAND, _this->Cls_OnCommand); HANDLE_MSG(hWnd, WM_SYSCOMMAND, _this->Cls_OnSysCommand); HANDLE_MSG(hWnd, WM_RBUTTONDOWN, _this->Cls_OnRButtonDown); /* Управление с трея */ case WM_USER + 200: { switch (lParam) { case WM_LBUTTONDOWN: { _this->DeleteIconOfTray(hWnd); break; } case WM_RBUTTONDOWN: { HMENU hContextByTray; POINT pos; GetCursorPos(&pos); hContextByTray = CreatePopupMenu(); AppendMenu(hContextByTray, MF_STRING, IDC_BTNPLAY, TEXT("Play")); AppendMenu(hContextByTray, MF_STRING, IDC_BTNPAUSE, TEXT("Pause")); AppendMenu(hContextByTray, MF_STRING, IDC_BTNSTOP, TEXT("Stop")); AppendMenu(hContextByTray, MF_STRING, IDC_NEXTSONG, TEXT("Next")); AppendMenu(hContextByTray, MF_STRING, IDC_PREVSONG, TEXT("Prev")); AppendMenu(hContextByTray, MF_SEPARATOR, 0, 0); AppendMenu(hContextByTray, MF_STRING, IDC_BTNCLOSE, TEXT("&Close")); SetForegroundWindow(hWnd); TrackPopupMenu(hContextByTray, TPM_LEFTALIGN, pos.x, pos.y, 0, hWnd, 0); DestroyMenu(hContextByTray); break; } default: break; } break; } case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); RECT rect; GetClientRect(hWnd, &rect); INT height = rect.bottom / 2 - 10; /* Initialization size rectangle by redraw spectrum */ _this->spectrRECT.left = rect.left; _this->spectrRECT.top = rect.top; _this->spectrRECT.right = rect.right; _this->spectrRECT.bottom = height; /* Yellow pen */ static int fred = 0 , fblue = 0, fgreen = 0; if (fred != _this->fill_red || fgreen != _this->fill_green || fblue != _this->fill_blue) { _this->black_brush = CreateSolidBrush ( RGB(_this->fill_red, _this->fill_green, _this->fill_blue) ); } fred = _this->fill_red; fgreen = _this->fill_green; fblue = _this->fill_blue; /* Red pen */ static int cred = 0, cgreen = 0, cblue = 0; if (cred != _this->contour_red || cblue != _this->contour_blue || cgreen != _this->contour_green) { _this->red_pen = CreatePen (PS_SOLID, 1, RGB(_this->contour_red, _this->contour_green, _this->contour_blue) ); } cred = _this->contour_red; cblue = _this->contour_blue; cgreen = _this->contour_green; int x; int y = height; int offset = 35; int columns = 77; //count columns int w = (rect.right - rect.left - 35) / columns; // ширина столбика FLOAT buffer_peaks[128] = { height }; BASS_ChannelGetData(_this->hStream, buffer_peaks, BASS_DATA_FFT256); for (int i = 0; i < columns;i++) { SelectPen(hdc, _this->red_pen); x = rect.left + offset + w * i; y = abs(buffer_peaks[i] * 400 * 3 - height); if (y > height) y = height; SelectObject(hdc, _this->black_brush); SelectPen(hdc, _this->red_pen); if (height - y > 1) Rectangle(hdc, x, y, x + w, height); } EndPaint(hWnd, &ps); ReleaseDC(hWnd, hdc); break; } case WM_CLOSE: { BASS_Free(); BASS_StreamFree(_this->hStream); EndDialog(hWnd, NULL); break; } default: return FALSE; } return FALSE; }
//----------------------------------------------------------------------------- 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 }
// update the spectrum display - the interesting bit :) void CALLBACK UpdateSpectrum(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) { HDC dc; int x,y,y1; if (specmode==3) { // waveform int c; float *buf; BASS_CHANNELINFO ci; memset(specbuf,0,SPECWIDTH*SPECHEIGHT); BASS_ChannelGetInfo(chan,&ci); // get number of channels buf=alloca(ci.chans*SPECWIDTH*sizeof(float)); // allocate buffer for data BASS_ChannelGetData(chan,buf,(ci.chans*SPECWIDTH*sizeof(float))|BASS_DATA_FLOAT); // get the sample data (floating-point to avoid 8 & 16 bit processing) for (c=0;c<ci.chans;c++) { for (x=0;x<SPECWIDTH;x++) { int v=(1-buf[x*ci.chans+c])*SPECHEIGHT/2; // invert and scale to fit display if (v<0) v=0; else if (v>=SPECHEIGHT) v=SPECHEIGHT-1; if (!x) y=v; do { // draw line from previous sample... if (y<v) y++; else if (y>v) y--; specbuf[y*SPECWIDTH+x]=c&1?127:1; // left=green, right=red (could add more colours to palette for more chans) } 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 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(sc))*1.7*SPECHEIGHT)-4; // scale it if (y>SPECHEIGHT) y=SPECHEIGHT; // cap it while (--y>=0) memset(specbuf+y*SPECWIDTH+x*(SPECWIDTH/BANDS),y+1,SPECWIDTH/BANDS-2); // 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); ReleaseDC(win,dc); }
void CALLBACK CustFXDSPProc (HFX hfx, DWORD chan, void* buf, DWORD len, HCustFX* hc) { BASS_StreamPutData(hc->push, buf, len); BASS_ChannelGetData(hc->pitch, buf, len); }
int Player::stateOfBuffer() { return BASS_ChannelGetData(_output,NULL,BASS_DATA_AVAILABLE); }
BOOL CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l) { switch (m) { case WM_TIMER: { // display current latency (input+output buffer level) char buf[20]; latency=(latency*3+BASS_ChannelGetData(chan,NULL,BASS_DATA_AVAILABLE) +BASS_ChannelGetData(rchan,NULL,BASS_DATA_AVAILABLE))/4; sprintf(buf,"%d",(int)(BASS_ChannelBytes2Seconds(chan,latency)*1000)); MESS(15,WM_SETTEXT,0,buf); } break; case WM_COMMAND: switch (LOWORD(w)) { case IDCANCEL: DestroyWindow(h); break; case 10: if (HIWORD(w)==CBN_SELCHANGE) { // input selection changed int i; float level; input=MESS(10,CB_GETCURSEL,0,0); // get the selection for (i=0;BASS_RecordSetInput(i,BASS_INPUT_OFF,-1);i++) ; // 1st disable all inputs, then... BASS_RecordSetInput(input,BASS_INPUT_ON,-1); // enable the selected input BASS_RecordGetInput(input,&level); // get the level MESS(11,TBM_SETPOS,TRUE,level*100); } break; case 20: // toggle chorus if (fx[0]) { BASS_ChannelRemoveFX(chan,fx[0]); fx[0]=0; } else fx[0]=BASS_ChannelSetFX(chan,BASS_FX_DX8_CHORUS,0); break; case 21: // toggle gargle if (fx[1]) { BASS_ChannelRemoveFX(chan,fx[1]); fx[1]=0; } else fx[1]=BASS_ChannelSetFX(chan,BASS_FX_DX8_GARGLE,0); break; case 22: // toggle reverb if (fx[2]) { BASS_ChannelRemoveFX(chan,fx[2]); fx[2]=0; } else fx[2]=BASS_ChannelSetFX(chan,BASS_FX_DX8_REVERB,0); break; case 23: // toggle flanger if (fx[3]) { BASS_ChannelRemoveFX(chan,fx[3]); fx[3]=0; } else fx[3]=BASS_ChannelSetFX(chan,BASS_FX_DX8_FLANGER,0); break; } break; case WM_HSCROLL: if (l) { // set input source level float level=SendMessage((HWND)l,TBM_GETPOS,0,0)/100.f; if (!BASS_RecordSetInput(input,0,level)) // failed to set input level BASS_RecordSetInput(-1,0,level); // try master level instead } break; case WM_INITDIALOG: win=h; MESS(11,TBM_SETRANGE,FALSE,MAKELONG(0,100)); // initialize input level slider MessageBox(win, "Do not set the input to 'WAVE' / 'What you hear' (etc...) with\n" "the level set high, as that is likely to result in nasty feedback.\n", "Feedback warning",MB_ICONWARNING); if (!Initialize()) { DestroyWindow(win); break; } SetTimer(h,1,250,NULL); return 1; case WM_DESTROY: KillTimer(h,1); // release it all BASS_RecordFree(); BASS_Free(); break; } return 0; }
// --[ Method ]--------------------------------------------------------------- // // - Class : CSoundStream // - prototype : bool GetFFT512(float* pfBuffer) const // // - Purpose : Gets the current FFT representation of the playing stream. // The buffer is filled with 512 floating point values. // // ----------------------------------------------------------------------------- bool CSoundStream::GetFFT512(float* pfBuffer) const { return BASS_ChannelGetData(m_handle, pfBuffer, BASS_DATA_FFT1024) != -1; }
void Spectrum::step(std::vector<DWORD> &rVecCurrentChannel) { //data[i] int nCount = 0; unsigned int *data3 = data + size * 2; for (unsigned int i = 0; i<size; i++) { data3[i] = 0; } for (int i = 0; i < rVecCurrentChannel.size(); i++) { unsigned int *data2 = data + size; float buf[256]; if (BASS_ChannelGetData( rVecCurrentChannel[i], buf, BASS_DATA_FFT512 ) == sizeof(buf)) { float maxf = 0; for (unsigned int i = 0; i<256; i++) { if (maxf < buf[i]) { maxf = buf[i]; } } for (unsigned int i = 0; i<size; i++) { data2[i] = height * (1 - buf[i * 50 / size] / maxf); if (data2[i] > height) data2[i] = height; if (data2[i] < 0) data2[i] = 0; data3[i] += data2[i]; } nCount++; } } if (nCount) { for (unsigned int i = 0; i<size; i++) { data[i] = (data[i] + 7 * data3[i]) / (nCount * 8); if (data[i] > height) data[i] = height; if (data[i] < 0) data[i] = 0; } } else { for (unsigned int i = 0; i<size; i++) { data[i] += rand()%3-1; if (data[i] > height) data[i] = height; if (data[i] < 0) data[i] = 0; } } }