void BassPlayer::playPreproccessing() { emit statusChanged(media_title, LoadedMedia); BASS_CHANNELINFO info; if (BASS_ChannelGetInfo(chan, &info)) channelsCount(info.chans); else channelsCount(2); if (eq_in_use) registerEQ(); #ifdef BASS_USE_TEMPO applyTempoToChannel(); newTempoProcessing(tempo()); #endif setSampleRateQuality(); newVolumeProcessing(volume()); newPanProcessing(pan()); if (BASS_ChannelPlay(chan, true)) { // stalled with big sized video files playPostprocessing(is_paused); syncHandle = BASS_ChannelSetSync((HSYNC)chan, BASS_SYNC_END, 0, &endTrackSync, this); syncDownloadHandle = BASS_ChannelSetSync(chan, BASS_SYNC_DOWNLOAD, 0, &endTrackDownloading, this); // BASS_SYNC_STALL // mixtime only Sync when playback of the channel is stalled/resumed. // param : not used. data : 0 = stalled, 1 = resumed. } else { proceedErrorState(); qCritical() << "IS NOT PLAYED"; } }
bool BassPlayer::fileInfo(const QUrl & uri, IMediaInfo * info) { bool currently_played = media_url.isValid() && uri == media_url; int chUID; if (currently_played) chUID = chan; else { if (uri.isLocalFile()) chUID = open(uri.toLocalFile(), LOCAL_PLAY_ATTRS); else chUID = openRemote(uri.toString(), REMOTE_PLAY_ATTRS); if (!chUID) return false; } float time = BASS_ChannelBytes2Seconds(chUID, BASS_ChannelGetLength(chUID, BASS_POS_BYTE)); // playback duration qint64 len = BASS_StreamGetFilePosition(chUID, BASS_FILEPOS_END); // file length info -> setDuration(time); info -> setBitrate((len / (125 * time) + 0.5)); BASS_CHANNELINFO media_info; if (BASS_ChannelGetInfo(chUID, &media_info)) { info -> setSize(len + BASS_StreamGetFilePosition(chUID, BASS_FILEPOS_START)); info -> setSampleRate(media_info.freq); info -> setChannels(media_info.chans); } if (!currently_played) BASS_StreamFree(chUID); return true; }
void OpenClicked(GtkButton *obj, gpointer data) { int resp=gtk_dialog_run(GTK_DIALOG(filesel)); gtk_widget_hide(filesel); if (resp==GTK_RESPONSE_ACCEPT) { char *file=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(filesel)); // free both MOD and stream, it must be one of them! :) BASS_MusicFree(chan); BASS_StreamFree(chan); if (!(chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_SAMPLE_LOOP|BASS_SAMPLE_FLOAT)) && !(chan=BASS_MusicLoad(FALSE,file,0,0,BASS_MUSIC_RAMPS|BASS_SAMPLE_LOOP|BASS_SAMPLE_FLOAT,1))) { // whatever it is, it ain't playable gtk_button_set_label(obj,"click here to open a file..."); Error("Can't play the file"); } else { BASS_CHANNELINFO info; BASS_ChannelGetInfo(chan,&info); if (info.chans!=2) { // the DSP expects stereo gtk_button_set_label(obj,"click here to open a file..."); BASS_MusicFree(chan); BASS_StreamFree(chan); Error("only stereo sources are supported"); } else { gtk_button_set_label(obj,file); // setup DSPs on new channel and play it RotateToggled(GTK_TOGGLE_BUTTON(GetWidget("rotate")),0); EchoToggled(GTK_TOGGLE_BUTTON(GetWidget("echo")),0); FlangerToggled(GTK_TOGGLE_BUTTON(GetWidget("flanger")),0); BASS_ChannelPlay(chan,FALSE); } } g_free(file); } }
BASS_CHANNELINFO * bmx_bass_getchannelinfo(DWORD handle) { BASS_CHANNELINFO * info = new BASS_CHANNELINFO; BOOL success = BASS_ChannelGetInfo(handle, info); if (!success) { delete info; return 0; } return info; }
pascal OSStatus OpenEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) { NavDialogRef fileDialog; NavDialogCreationOptions fo; NavGetDefaultDialogCreationOptions(&fo); fo.optionFlags=0; fo.parentWindow=win; NavCreateChooseFileDialog(&fo,NULL,NULL,NULL,NULL,NULL,&fileDialog); // if someone wants to somehow get the file selector to filter like in the Windows example, that'd be nice ;) if (!NavDialogRun(fileDialog)) { NavReplyRecord r; if (!NavDialogGetReply(fileDialog,&r)) { AEKeyword k; FSRef fr; if (!AEGetNthPtr(&r.selection,1,typeFSRef,&k,NULL,&fr,sizeof(fr),NULL)) { char file[256]; FSRefMakePath(&fr,(BYTE*)file,sizeof(file)); BASS_StreamFree(chan); // free old stream before opening new if (!(chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_SAMPLE_LOOP|BASS_SAMPLE_FLOAT))) { SetControlTitleWithCFString(inUserData,CFSTR("click here to open a file...")); { ControlRef cref=GetControl(11); SetControlData(cref,kControlNoPart,kControlStaticTextTextTag,0,""); DrawOneControl(cref); } SetControl32BitMaximum(GetControl(12),0); Error("Can't play the file"); } else { CFStringRef cs=CFStringCreateWithCString(0,file,kCFStringEncodingUTF8); SetControlTitleWithCFString(inUserData,cs); CFRelease(cs); { // display the file type and length QWORD bytes=BASS_ChannelGetLength(chan,BASS_POS_BYTE); DWORD time=BASS_ChannelBytes2Seconds(chan,bytes); BASS_CHANNELINFO info; BASS_ChannelGetInfo(chan,&info); sprintf(file,"channel type = %x (%s)\nlength = %llu (%u:%02u)", info.ctype,GetCTypeString(info.ctype,info.plugin),bytes,time/60,time%60); { ControlRef cref=GetControl(11); SetControlData(cref,kControlNoPart,kControlStaticTextTextTag,strlen(file),file); DrawOneControl(cref); } SetControl32BitMaximum(GetControl(12),time); // update scroller range } BASS_ChannelPlay(chan,FALSE); } } NavDisposeReply(&r); } } NavDialogDispose(fileDialog); return noErr; }
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 BassDecoder::_load(const uint8_t* buffer, unsigned int size) { _mod=false; #if defined(LIBTOOLS_WINDOWS) && !defined(BASS_H) if (BASS_MusicLoad && BASS_StreamCreateFile && BASS_ChannelGetInfo) { #endif if (_music=BASS_MusicLoad(TRUE, (void*) buffer, 0,size, BASS_MUSIC_PRESCAN | BASS_MUSIC_DECODE | BASS_SAMPLE_FLOAT, Signal::frequency)) { _mod=true; } else if (_music=BASS_StreamCreateFile(TRUE, (void*) buffer, 0, size, BASS_STREAM_PRESCAN | BASS_STREAM_DECODE | BASS_SAMPLE_FLOAT)); if (_music) { BASS_ChannelGetInfo((DWORD)_music,&_infos); _bytesFrame= sizeof(float)*Signal::size*_infos.chans; _samplesForSignals = (float*) realloc(_samplesForSignals,_bytesFrame); _sampleRate=_infos.freq; if (_sampleRate != Signal::frequency) std::cout << "warning : file rate (" << _sampleRate << "Hz) is different of " << Signal::frequency << "Hz" << std::endl; _ended=false; if (prepareDecode()) { decodeID3v1(); decodeOGGTag(); } } #if defined(LIBTOOLS_WINDOWS) && !defined(BASS_H) } else { std::cerr << "Error missing bass fonctions in DLL " << std::endl; } #endif return (_music); }
HFX CALLBACK SetCustFX (DWORD chan, DWORD type, int priority) { if (type!=CUST_FX_TYPE_ID) return NULL; BASS_CHANNELINFO info; BASS_ChannelGetInfo(chan, &info); HCustFX* hc = malloc(sizeof(HCustFX)); if (!hc) return NULL; hc->flags = info.flags&( BASS_SAMPLE_FLOAT | BASS_SAMPLE_8BITS ); hc->push = BASS_StreamCreate(info.freq, info.chans, hc->flags | BASS_STREAM_DECODE, STREAMPROC_PUSH, NULL); hc->pitch = BASS_FX_TempoCreate(hc->push, BASS_STREAM_DECODE); HFX hfx = bassfunc->SetFX(chan, CustFXDSPProc, hc, priority, &CustFXFuncs); if (hfx&&hc->pitch&&hc->push) return hfx; if (hfx) BASS_ChannelRemoveFX(chan, hfx); if (hc->pitch) BASS_StreamFree(hc->pitch); if (hc->push) BASS_StreamFree(hc->push); free(hc); return NULL; }
bool openProcess(BASS_VST_PLUGIN* this_, BASS_VST_PLUGIN* info_) { // really not yet opened? if( this_->effStartProcessCalled ) { return false; } // do we have a BASS handle? if( info_->channelHandle == 0 ) { return false; } // get information about the channel BASS_CHANNELINFO channelInfo; if( !BASS_ChannelGetInfo(info_->channelHandle, &channelInfo) ) { return false; // error already logged } enterVstCritical(this_); // connect the inputs and outputs int i; for( i = 0; i < info_->aeffect->numInputs; i++ ) { this_->aeffect->dispatcher(this_->aeffect, __effConnectInputDeprecated, i, i<(int)channelInfo.chans? 1/*connect*/ : 0/*disconnect*/, NULL, 0.0); } for( i = 0; i < info_->aeffect->numOutputs; i++ ) { this_->aeffect->dispatcher(this_->aeffect, __effConnectOutputDeprecated, i, i<(int)channelInfo.chans? 1/*connect*/ : 0/*disconnect*/, NULL, 0.0); } // notify the plugin that we will start processing this_->aeffect->dispatcher(this_->aeffect, effStartProcess, 0, 0, NULL, 0.0); this_->effStartProcessCalled = true; leaveVstCritical(this_); 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; }
// // 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; }
void CALLBACK doEffectProcess(HDSP dspHandle, DWORD channelHandle, void* buffer__, DWORD bufferBytes__, USERPTR vstHandle__) { DWORD vstHandle = (DWORD)vstHandle__; BASS_CHANNELINFO channelInfo; int i; long requiredInputs; long requiredOutputs; float* floatBuffer; long numSamples; bool cnvPcm2Float; bool cnvMonoToStereo = false; BASS_VST_PLUGIN* this_ = refHandle(vstHandle); if( this_ == NULL || channelHandle != this_->channelHandle || dspHandle != this_->dspHandle || buffer__ == NULL || bufferBytes__ <= 0 ) goto Cleanup; // error already logged // get the channel information if( !BASS_ChannelGetInfo(channelHandle, &channelInfo) || channelInfo.chans <= 0 ) goto Cleanup; requiredInputs = this_->aeffect->numInputs; if( (long)channelInfo.chans > requiredInputs ) requiredInputs = channelInfo.chans; requiredOutputs = this_->aeffect->numOutputs; if( (long)channelInfo.chans > requiredOutputs ) requiredOutputs = channelInfo.chans; // get the data as floats. // this is not lossy. cnvPcm2Float = ((channelInfo.flags&BASS_SAMPLE_FLOAT)==0 && (this_->type==VSTinstrument || BASS_GetConfig(BASS_CONFIG_FLOATDSP)==0)); if( cnvPcm2Float ) { if( channelInfo.flags & BASS_SAMPLE_8BITS ) goto Cleanup; // can't and won't do this if( !allocTempBuffer(this_, bufferBytes__*2) ) goto Cleanup; cnvPcm16ToFloat((signed short*)buffer__, this_->bufferTemp, bufferBytes__); floatBuffer = this_->bufferTemp; numSamples = (bufferBytes__ / sizeof(signed short)) / channelInfo.chans; } else { floatBuffer = (float*)buffer__; numSamples = (bufferBytes__ / sizeof(float)) / channelInfo.chans; } if( numSamples <= 0 ) goto Cleanup; // copy the given LRLRLR buffer to the VST LLLRRR buffers // this is not lossy if( !allocChanBuffers(this_, requiredInputs, requiredOutputs, numSamples*sizeof(float)) ) goto Cleanup; { long chans = channelInfo.chans, c = 0; float* buffer = (float*)floatBuffer; float* end = &buffer[numSamples * chans]; float** in = this_->buffersIn; i = 0; while( buffer < end ) { in[c][i] = *buffer; buffer ++; c++; if( c == chans ) { c = 0; i++; } } for( c = chans; c < requiredInputs; c++ ) memset(in[c], 0, numSamples * sizeof(float)); } // special mono-processing effect handling if( this_->aeffect->numInputs == 1 && this_->aeffect->numOutputs <= 2 && channelInfo.chans > 1 && !(this_->createFlags&BASS_VST_KEEP_CHANS) ) { cnvFloatLLRR_To_Mono(this_->buffersIn[0], this_->buffersIn[1], numSamples, this_->aeffect->numOutputs == 1? 1.0F : 0.5F); if( this_->aeffect->numOutputs == 1 ) cnvMonoToStereo = true; } // empty the output buffers and process // (normally this is needed only for process() and not for processReplacing(); // however, this has to be done even in processReplacing() since some VSTIs // (most notably those from Steinberg... hehe) obviously don't implement // processReplacing() as a separate function but rather use process()) enterVstCritical(this_); if( !this_->doBypass ) { this_->vstTimeInfo.samplePos += numSamples; if( this_->vstTimeInfo.samplePos < 0.0 ) this_->vstTimeInfo.samplePos = 0.0; EnterCriticalSection(&s_forwardCritical); for( i = 0; i < this_->forwardDataToOtherCnt; i++ ) { clearOutputBuffers(this_, numSamples); BASS_VST_PLUGIN* other_ = refHandle(this_->forwardDataToOtherVstHandles[i]); if( other_ ) { if( tryEnterVstCritical(other_) ) { callProcess(other_, this_/*buffers to use*/, numSamples); leaveVstCritical(other_); } } unrefHandle(this_->forwardDataToOtherVstHandles[i]); } LeaveCriticalSection(&s_forwardCritical); // the "real" sound processing (the one above is only for the editors to get data) clearOutputBuffers(this_, numSamples); callProcess(this_, this_/*buffers to use*/, numSamples); // special mono-processing effect handling if( cnvMonoToStereo ) { cnvFloatLLRR_To_Stereo(this_->buffersOut[0], this_->buffersOut[1], numSamples); } // convert the returned data back to our channel representation (LLLLLRRRRR to LRLRLRLR) // this is not lossy { long chans = channelInfo.chans, c = 0; float* buffer = (float*)floatBuffer; float* end = &buffer[numSamples * chans]; float** out = this_->buffersOut; i = 0; while( buffer < end ) { *buffer = out[c][i]; buffer++; c++; if( c == chans ) { c = 0; i++; } } } // convert the data back to PCM, if needed // this is lossy if( cnvPcm2Float ) { cnvFloatToPcm16(floatBuffer, (signed short*)buffer__, numSamples * sizeof(float) * channelInfo.chans); } } leaveVstCritical(this_); // done Cleanup: unrefHandle(vstHandle); }
// 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); }
BOOL CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l) { switch (m) { case WM_COMMAND: switch (LOWORD(w)) { case IDCANCEL: DestroyWindow(h); break; case 10: { BASS_CHANNELINFO info; char file[MAX_PATH]=""; ofn.lpstrFilter="playable files\0*.mo3;*.xm;*.mod;*.s3m;*.it;*.mtm;*.umx;*.mp3;*.mp2;*.mp1;*.ogg;*.wav;*.aif\0All files\0*.*\0\0"; ofn.lpstrFile=file; if (GetOpenFileName(&ofn)) { // free both MOD and stream, it must be one of them! :) BASS_MusicFree(chan); BASS_StreamFree(chan); if (!(chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_SAMPLE_LOOP|floatable)) && !(chan=BASS_MusicLoad(FALSE,file,0,0,BASS_SAMPLE_LOOP|BASS_MUSIC_RAMPS|floatable,1))) { // whatever it is, it ain't playable MESS(10,WM_SETTEXT,0,"click here to open a file..."); Error("Can't play the file"); break; } BASS_ChannelGetInfo(chan,&info); if (info.chans!=2) { // only stereo is allowed MESS(10,WM_SETTEXT,0,"click here to open a file..."); BASS_MusicFree(chan); BASS_StreamFree(chan); Error("only stereo sources are supported"); break; } MESS(10,WM_SETTEXT,0,file); // setup DSPs on new channel and play it SendMessage(win,WM_COMMAND,11,0); SendMessage(win,WM_COMMAND,12,0); SendMessage(win,WM_COMMAND,13,0); BASS_ChannelPlay(chan,FALSE); } } break; case 11: // toggle "rotate" if (MESS(11,BM_GETCHECK,0,0)) { rotpos=0.7853981f; rotdsp=BASS_ChannelSetDSP(chan,&Rotate,0,2); } else BASS_ChannelRemoveDSP(chan,rotdsp); break; case 12: // toggle "echo" if (MESS(12,BM_GETCHECK,0,0)) { memset(echbuf,0,sizeof(echbuf)); echpos=0; echdsp=BASS_ChannelSetDSP(chan,&Echo,0,1); } else BASS_ChannelRemoveDSP(chan,echdsp); break; case 13: // toggle "flanger" if (MESS(13,BM_GETCHECK,0,0)) { memset(flabuf,0,sizeof(flabuf)); flapos=0; flas=FLABUFLEN/2; flasinc=0.002f; fladsp=BASS_ChannelSetDSP(chan,&Flange,0,0); } else BASS_ChannelRemoveDSP(chan,fladsp); break; } break; case WM_INITDIALOG: win=h; memset(&ofn,0,sizeof(ofn)); ofn.lStructSize=sizeof(ofn); ofn.hwndOwner=h; ofn.nMaxFile=MAX_PATH; ofn.Flags=OFN_HIDEREADONLY|OFN_EXPLORER; // enable floating-point DSP BASS_SetConfig(BASS_CONFIG_FLOATDSP,TRUE); // initialize - default device if (!BASS_Init(-1,44100,0,win,NULL)) { Error("Can't initialize device"); DestroyWindow(win); break; } // check for floating-point capability floatable=BASS_StreamCreate(44100,2,BASS_SAMPLE_FLOAT,NULL,0); if (floatable) { // woohoo! BASS_StreamFree(floatable); floatable=BASS_SAMPLE_FLOAT; } return 1; case WM_DESTROY: BASS_Free(); break; } return 0; }
INT_PTR CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l) { switch (m) { case WM_COMMAND: switch (LOWORD(w)) { case IDCANCEL: DestroyWindow(h); break; case 10: { char file[MAX_PATH]=""; ofn.lpstrFile=file; ofn.nMaxFile=MAX_PATH; if (GetOpenFileName(&ofn)) { BASS_StreamFree(chan); // free the old stream if (!(chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_SAMPLE_LOOP))) { // it ain't playable MESS(10,WM_SETTEXT,0,"click here to open a file..."); MESS(11,WM_SETTEXT,0,""); Error("Can't play the file"); break; } MESS(10,WM_SETTEXT,0,file); { // display the file type and length QWORD bytes=BASS_ChannelGetLength(chan,BASS_POS_BYTE); DWORD time=BASS_ChannelBytes2Seconds(chan,bytes); BASS_CHANNELINFO info; BASS_ChannelGetInfo(chan,&info); sprintf(file,"channel type = %x (%s)\nlength = %I64u (%u:%02u)", info.ctype,GetCTypeString(info.ctype,info.plugin),bytes,time/60,time%60); MESS(11,WM_SETTEXT,0,file); MESS(12,TBM_SETRANGE,1,MAKELONG(0,time)); // update scroller range } BASS_ChannelPlay(chan,FALSE); } } break; } break; case WM_HSCROLL: if (l && LOWORD(w)!=SB_THUMBPOSITION && LOWORD(w)!=SB_ENDSCROLL) { // set the position int pos=SendMessage((HWND)l,TBM_GETPOS,0,0); BASS_ChannelSetPosition(chan,BASS_ChannelSeconds2Bytes(chan,pos),BASS_POS_BYTE); } break; case WM_TIMER: MESS(12,TBM_SETPOS,1,(DWORD)BASS_ChannelBytes2Seconds(chan,BASS_ChannelGetPosition(chan,BASS_POS_BYTE))); // update position break; case WM_INITDIALOG: win=h; // initialize default output device if (!BASS_Init(-1,44100,0,win,NULL)) { Error("Can't initialize device"); DestroyWindow(win); break; } // initialize file selector memset(&ofn,0,sizeof(ofn)); ofn.lStructSize=sizeof(ofn); ofn.hwndOwner=h; ofn.Flags=OFN_HIDEREADONLY|OFN_EXPLORER; ofn.lpstrFilter=filter; memcpy(filter,"BASS built-in (*.mp3;*.mp2;*.mp1;*.ogg;*.wav;*.aif)\0*.mp3;*.mp2;*.mp1;*.ogg;*.wav;*.aif\0",88); { // look for plugins (in the executable's directory) WIN32_FIND_DATA fd; HANDLE fh; char path[MAX_PATH],*fp=filter+88; GetModuleFileName(0,path,sizeof(path)); strcpy(strrchr(path,'\\')+1,"bass*.dll"); fh=FindFirstFile(path,&fd); if (fh!=INVALID_HANDLE_VALUE) { do { HPLUGIN plug; if (plug=BASS_PluginLoad(fd.cFileName,0)) { // plugin loaded... const BASS_PLUGININFO *pinfo=BASS_PluginGetInfo(plug); // get plugin info to add to the file selector filter... int a; for (a=0;a<pinfo->formatc;a++) { fp+=sprintf(fp,"%s (%s) - %s",pinfo->formats[a].name,pinfo->formats[a].exts,fd.cFileName)+1; // format description fp+=sprintf(fp,"%s",pinfo->formats[a].exts)+1; // extension filter } // add plugin to the list MESS(20,LB_ADDSTRING,0,fd.cFileName); } } while (FindNextFile(fh,&fd)); FindClose(fh); } if (!MESS(20,LB_GETCOUNT,0,0)) // no plugins... MESS(20,LB_ADDSTRING,0,"no plugins - visit the BASS webpage to get some"); memcpy(fp,"All files\0*.*\0\0",15); } SetTimer(h,0,500,0); // timer to update the position return 1; case WM_DESTROY: // "free" the output device and all plugins BASS_Free(); BASS_PluginFree(0); break; } return 0; }
bool BassDecoder::_open(const string_t& filename) { _mod=false; #if defined(LIBTOOLS_WINDOWS) && !defined(BASS_H) if (BASS_MusicLoad && BASS_StreamCreateFile && BASS_StreamCreateURL && BASS_ChannelGetInfo) { #endif //std::wcerr << "Try loading: " << filename.toWideString() << std::endl; bass_unicode_string_t bass_unicode_str=string_t_to_bass_unicode_string_t(filename); void* unicode_filename=(void*)bass_unicode_str.c_str(); if (_music=BASS_MusicLoad(FALSE, unicode_filename, 0,0, BASS_MUSIC_PRESCAN | BASS_MUSIC_DECODE | BASS_SAMPLE_FLOAT | BASS_UNICODE, Signal::frequency)) { _mod=true; } else if (_music=BASS_StreamCreateFile(FALSE, unicode_filename, 0,0, BASS_STREAM_PRESCAN | BASS_STREAM_DECODE | BASS_SAMPLE_FLOAT | BASS_UNICODE)); else if (_music=BASS_StreamCreateURL((const char *)unicode_filename,0, BASS_STREAM_DECODE | BASS_SAMPLE_FLOAT | BASS_UNICODE, (DOWNLOADPROC*) 0, (void*)0)); if (_music) { BASS_ChannelGetInfo((DWORD)_music,&_infos); _bytesFrame= sizeof(float)*Signal::size*_infos.chans; _samplesForSignals = (float*) realloc(_samplesForSignals,_bytesFrame); _sampleRate=_infos.freq; if (_sampleRate != Signal::frequency) { #ifndef NDEBUG std::cout << "warning : file rate (" << _sampleRate << "Hz) is different of " << Signal::frequency << "Hz" << std::endl; #endif } _ended=false; if (prepareDecode()) { decodeID3v1(); decodeOGGTag(); } } #if defined(LIBTOOLS_WINDOWS) && !defined(BASS_H) } else { #ifndef NDEBUG std::cerr << "Error missing bass fonctions in DLL " << std::endl; #endif } #endif return (_music); }
// 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; }
int main(int argc, char **argv) { std::cerr << "Start\n"; HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, "sc_shared"); if(hMapFile == NULL) { return -10; } Shared *shared; shared = (Shared*)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(*shared)); if(shared == NULL) { return -11; } std::string recDev = getopt(argc, argv, "--recDev="); //int sc_version = std::stoi(getopt(argc, argv, "--version=")); BASS_SetConfig(BASS_CONFIG_UNICODE, true); int recDevNo = -1; BASS_DEVICEINFO info; for(int i=0; BASS_RecordGetDeviceInfo(i, &info); i++) { if(recDev == std::to_string(hash_str(info.name))) { recDevNo = i; break; } } if(!BASS_RecordInit(recDevNo)) { int code = BASS_ErrorGetCode(); std::string text = "BASS error: " + std::to_string(code); if(code == 23) text += "\nProblem with device: \"" + recDev + "\"!"; std::cerr << text << "\n"; return -1; } int sampleRate = std::stoi(getopt(argc, argv, "--samplerate=")); int channels = std::stoi(getopt(argc, argv, "--channels=")); recStream = BASS_RecordStart(sampleRate, channels, 0, RecordProc, nullptr); #ifdef _WIN32 std::string lameBin = "lame.exe"; #else std::string lameBin = "lame"; #endif HENCODE encoder = BASS_Encode_Start(recStream, (lameBin + " -b " + getopt(argc, argv, "--bitrate=") + " -").c_str(), 0, NULL, 0); bool ok = BASS_Encode_CastInit(encoder, getopt(argc, argv, "--url=").c_str(), getopt(argc, argv, "--password="******"--bitrate=")), FALSE); if(!ok) { int code = BASS_ErrorGetCode(); std::string text = "BASS error: " + std::to_string(code); std::cerr << text << "\n"; return -2; } std::cerr << "OK\n"; while(!shared->end) { if(BASS_Encode_IsActive(encoder) != BASS_ACTIVE_PLAYING) { return -3; } BASS_CHANNELINFO info; if(BASS_ChannelGetInfo(recStream, &info)) { DWORD flags = info.chans == 1 ? BASS_LEVEL_MONO : BASS_LEVEL_STEREO; BASS_ChannelGetLevelEx(recStream, shared->levels, 0.035f, flags); } Sleep(35); } std::cerr << "End\n"; UnmapViewOfFile((LPCVOID)shared); CloseHandle(hMapFile); return 0; }