// set dsp eq void SetDSP_EQ(float fGain, float fBandwidth, float fQ, float fCenter_Bass, float fCenter_Mid, float fCenter_Treble) { BASS_BFX_PEAKEQ eq; // set peaking equalizer effect with no bands fxEQ=BASS_ChannelSetFX(chan, BASS_FX_BFX_PEAKEQ,0); eq.fGain=fGain; eq.fQ=fQ; eq.fBandwidth=fBandwidth; eq.lChannel=BASS_BFX_CHANALL; // create 1st band for bass eq.lBand=0; eq.fCenter=fCenter_Bass; BASS_FXSetParameters(fxEQ, &eq); // create 2nd band for mid eq.lBand=1; eq.fCenter=fCenter_Mid; BASS_FXSetParameters(fxEQ, &eq); // create 3rd band for treble eq.lBand=2; eq.fCenter=fCenter_Treble; BASS_FXSetParameters(fxEQ, &eq); // update dsp eq UpdateFX(0); UpdateFX(1); UpdateFX(2); }
bool CClientSound::SetFxEffect ( int iFxEffect, bool bEnable ) { if ( m_pSound ) { if ( iFxEffect >= 0 ) { if ( bEnable ) { if ( !m_FxEffects[iFxEffect] ) { m_FxEffects[iFxEffect] = BASS_ChannelSetFX ( m_pSound, iFxEffect, 0 ); if ( m_FxEffects[iFxEffect] ) return true; } } else { if ( BASS_ChannelRemoveFX ( m_pSound, m_FxEffects[iFxEffect] ) ) { m_FxEffects[iFxEffect] = 0; return true; } } } } return false; }
bool TEffect::ApplyInternal(bass_p pChannel) { if (IsRemoved()) return false; bUpdated = true; iErrorCode = BASS_OK; if (eType == BASS_FX_UNKNOWN) { iErrorCode = BASS_ERROR_ILLPARAM; return false; } if (pChannel == BASS_NULL) { iErrorCode = BASS_ERROR_HANDLE; return false; } bass_p pOldChannel = this->pChannel; if (pOldChannel != pChannel) { this->pChannel = pChannel; if (pOldChannel != BASS_NULL && pFX != BASS_NULL) { BASS_ChannelRemoveFX(pOldChannel, pFX); pFX = BASS_NULL; } } else { if (pFX != BASS_NULL && bEnabled) { return true; } } if (!bEnabled) { RemoveFX(); return true; } pFX = BASS_ChannelSetFX(pChannel, eType, 0); iErrorCode = BASS_ErrorGetCode(); if (iErrorCode != BASS_OK) { RemoveFX(); return false; } UpdateInternal(); ResetInternal(); return true; }
void FXToggled(GtkToggleButton *obj, gpointer data) { // toggle effects const gchar *objname=gtk_widget_get_name(GTK_WIDGET(obj)); int n=atoi(objname+2); if (fx[n]) { BASS_ChannelRemoveFX(stream,fx[n]); fx[n]=0; } else fx[n]=BASS_ChannelSetFX(stream,fxtype[n],0); }
bool BassPlayer::registerEQ() { if (_fxEQ) unregisterEQ(); if ((_fxEQ = BASS_ChannelSetFX(chan, BASS_FX_BFX_PEAKEQ, 0))) { BASS_BFX_PEAKEQ eq; eq.fQ = 0; eq.fBandwidth = currentPresetBase(); eq.lChannel = BASS_BFX_CHANALL; QMap<float, QString> eqBands = bands(); QMap<float, QString>::Iterator band = eqBands.begin(); for(int num = 0; band != eqBands.end(); band++, num++) { eq.fGain = eqBandsGains.value(num, 0); eq.lBand = num; eq.fCenter = band.key(); BASS_FXSetParameters(_fxEQ, &eq); } } return _fxEQ != 0; }
// // Copy state stored in m_EnabledEffects to actual BASS sound // void CBassAudio::ApplyFxEffects(void) { for (uint i = 0; i < NUMELMS(m_FxEffects) && NUMELMS(m_EnabledEffects); i++) { if (m_EnabledEffects[i] && !m_FxEffects[i]) { // Switch on m_FxEffects[i] = BASS_ChannelSetFX(m_pSound, i, 0); if (!m_FxEffects[i]) m_FxEffects[i] = INVALID_FX_HANDLE; } else if (!m_EnabledEffects[i] && m_FxEffects[i]) { // Switch off if (m_FxEffects[i] != INVALID_FX_HANDLE) BASS_ChannelRemoveFX(m_pSound, m_FxEffects[i]); m_FxEffects[i] = 0; } } }
BOOL CALLBACK dialogproc(HWND h,UINT m,WPARAM w,LPARAM l) { DWORD a=0; float freq; char c[30]; BASS_BFX_PEAKEQ eq; // dsp peaking equalizer BASS_BFX_PHASER phs; // dsp phaser switch (m) { case WM_COMMAND: switch (LOWORD(w)) { case ID_OPEN: { char file[MAX_PATH]=""; ofn.lpstrFilter="playable files\0*.mo3;*.xm;*.mod;*.s3m;*.it;*.mtm;*.mp3;*.mp2;*.mp1;*.ogg;*.wav;*.aif\0All files\0*.*\0\0"; ofn.lpstrFile=file; if (GetOpenFileName(&ofn)) { memcpy(path,file,ofn.nFileOffset); path[ofn.nFileOffset-1]=0; // free previous dsp effects & handles BASS_StreamFree(chan); // free stream BASS_MusicFree(chan); // free music if(!(chan=BASS_StreamCreateFile(FALSE, file, 0, 0, BASS_SAMPLE_LOOP|floatable))&& !(chan=BASS_MusicLoad(FALSE, file, 0, 0, BASS_MUSIC_LOOP|BASS_MUSIC_RAMP|floatable,0))){ // not a WAV/MP3 or MOD MESS(ID_OPEN,WM_SETTEXT,0,"click here to open a file && play it..."); Error("Selected file couldnt be loaded!"); break; } // update the Button to show the loaded file name MESS(ID_OPEN,WM_SETTEXT,0,GetFileName(file)); // set dsp effects SendMessage(win,WM_COMMAND,IDC_CHKEQ,l); SendMessage(win,WM_COMMAND,IDC_CHKPHS,l); // get current sample rate BASS_ChannelGetAttribute(chan, BASS_ATTRIB_FREQ, &freq); oldfreq = freq; // set the dx sample rate & view MESS(IDC_DXRATE,TBM_SETRANGEMAX,0,(long)(freq * 1.3f)); MESS(IDC_DXRATE,TBM_SETRANGEMIN,0,(long)(freq * 0.7f)); MESS(IDC_DXRATE,TBM_SETPOS,TRUE,(long)freq); MESS(IDC_DXRATE,TBM_SETPAGESIZE,0,(long)(freq * 0.01f)); // by 1% sprintf(c,"DirectX Samplerate = %dHz", (long)freq); MESS(IDC_SDXRATE,WM_SETTEXT,0,c); // play it! BASS_ChannelPlay(chan, FALSE); } } return 1; case IDC_CHKEQ: if (MESS(IDC_CHKEQ,BM_GETCHECK,0,0)) SetDSP_EQ(0.0f, 2.5f, 0.0f, 125.0f, 1000.0f, 8000.0f); else BASS_ChannelRemoveFX(chan, fxEQ); return 1; case IDC_CHKPHS: if(MESS(IDC_CHKPHS,BM_GETCHECK,0,0)){ fxPhaser=BASS_ChannelSetFX(chan, BASS_FX_BFX_PHASER,0); BASS_FXGetParameters(fxPhaser, &phs); phs.fWetMix = (float)MESS(IDC_WETMIX,TBM_GETPOS,0,0) / 1000.0f; phs.fDryMix = (float)MESS(IDC_DRYMIX,TBM_GETPOS,0,0) / 1000.0f; phs.fFeedback = (float)MESS(IDC_FEEDBACK,TBM_GETPOS,0,0) / 1000.0f; phs.fRate = (float)MESS(IDC_RATE,TBM_GETPOS,0,0) / 10.0f; phs.fRange = (float)MESS(IDC_RANGE,TBM_GETPOS,0,0) / 10.0f; phs.fFreq = (float)MESS(IDC_FREQ,TBM_GETPOS,0,0) / 10.0f; BASS_FXSetParameters(fxPhaser, &phs); }else BASS_ChannelRemoveFX(chan, fxPhaser); return 1; } return 1; case WM_VSCROLL: if(l){ UpdateFX(GetDlgCtrlID((HWND)l)-IDC_SLDEQ1); } return 1; case WM_HSCROLL: if(!BASS_ChannelIsActive(chan)) break; switch (GetDlgCtrlID((HWND)l)) { case IDC_DXRATE: BASS_ChannelSetAttribute(chan, BASS_ATTRIB_FREQ, (float)MESS(IDC_DXRATE, TBM_GETPOS, 0, 0)); sprintf(c,"DirectX Samplerate = %dHz", MESS(IDC_DXRATE, TBM_GETPOS, 0, 0)); MESS(IDC_SDXRATE,WM_SETTEXT,0,c); // update all bands fCenters after changing samplerate { int i; for(i=0;i<3;i++){ eq.lBand = i; BASS_FXGetParameters(fxEQ, &eq); eq.fCenter = eq.fCenter * (float)MESS(IDC_DXRATE, TBM_GETPOS, 0, 0) / oldfreq; BASS_FXSetParameters(fxEQ, &eq); } oldfreq = (float)MESS(IDC_DXRATE, TBM_GETPOS, 0, 0); } break; case IDC_DRYMIX: case IDC_WETMIX: case IDC_FEEDBACK: case IDC_RATE: case IDC_RANGE: case IDC_FREQ: BASS_FXGetParameters(fxPhaser, &phs); phs.fWetMix = (float)MESS(IDC_WETMIX,TBM_GETPOS,0,0) / 1000.0f; phs.fDryMix = (float)MESS(IDC_DRYMIX,TBM_GETPOS,0,0) / 1000.0f; phs.fFeedback = (float)MESS(IDC_FEEDBACK,TBM_GETPOS,0,0) / 1000.0f; phs.fRate = (float)MESS(IDC_RATE,TBM_GETPOS,0,0) / 10.0f; phs.fRange = (float)MESS(IDC_RANGE,TBM_GETPOS,0,0) / 10.0f; phs.fFreq = (float)MESS(IDC_FREQ,TBM_GETPOS,0,0) / 10.0f; BASS_FXSetParameters(fxPhaser, &phs); } return 1; case WM_INITDIALOG: win=h; GetCurrentDirectory(MAX_PATH,path); memset(&ofn,0,sizeof(ofn)); ofn.lStructSize=sizeof(ofn); ofn.hwndOwner=h; ofn.hInstance=inst; ofn.nMaxFile=MAX_PATH; ofn.Flags=OFN_HIDEREADONLY|OFN_EXPLORER; // enable floating-point DSP BASS_SetConfig(BASS_CONFIG_FLOATDSP, TRUE); // setup output - default device, 44100hz, stereo, 16 bits if (!BASS_Init(-1,44100,0,win,NULL)) { Error("Can't initialize device"); DestroyWindow(win); return 1; } // check for floating-point capability floatable = BASS_StreamCreate(44100, 2, BASS_SAMPLE_FLOAT, 0, 0); if (floatable) { BASS_StreamFree(floatable); //woohoo! floatable = BASS_SAMPLE_FLOAT; } // initialize dsp eq sliders MESS(IDC_SLDEQ1,TBM_SETRANGE,FALSE,MAKELONG(0,20)); MESS(IDC_SLDEQ1,TBM_SETPOS,TRUE,10); MESS(IDC_SLDEQ2,TBM_SETRANGE,FALSE,MAKELONG(0,20)); MESS(IDC_SLDEQ2,TBM_SETPOS,TRUE,10); MESS(IDC_SLDEQ3,TBM_SETRANGE,FALSE,MAKELONG(0,20)); MESS(IDC_SLDEQ3,TBM_SETPOS,TRUE,10); // dx rate MESS(IDC_DXRATE,TBM_SETRANGEMAX,0,(long)(44100.0f*1.3f)); MESS(IDC_DXRATE,TBM_SETRANGEMIN,0,(long)(44100.0f*0.7f)); MESS(IDC_DXRATE,TBM_SETPOS,TRUE,44100); MESS(IDC_DXRATE,TBM_SETPAGESIZE,0,(long)(44100.0f*0.01f)); // by 1% // DryMix MESS(IDC_DRYMIX,TBM_SETRANGE,0,MAKELONG(-2000,2000)); MESS(IDC_DRYMIX,TBM_SETPOS,TRUE,-999); // WetMix MESS(IDC_WETMIX,TBM_SETRANGE,0,MAKELONG(-2000,2000)); MESS(IDC_WETMIX,TBM_SETPOS,TRUE,999); // Feedback MESS(IDC_FEEDBACK,TBM_SETRANGE,0,MAKELONG(-1000,1000)); MESS(IDC_FEEDBACK,TBM_SETPOS,TRUE,-60); // Rate MESS(IDC_RATE,TBM_SETRANGE,0,MAKELONG(0,100)); MESS(IDC_RATE,TBM_SETPOS,TRUE,2); // Range MESS(IDC_RANGE,TBM_SETRANGE,0,MAKELONG(0,100)); MESS(IDC_RANGE,TBM_SETPOS,TRUE,60); // Freq MESS(IDC_FREQ,TBM_SETRANGE,0,MAKELONG(0,10000)); MESS(IDC_FREQ,TBM_SETPOS,TRUE,1000); Font=CreateFont(-12,0,0,0,FW_BOLD,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_STRING_PRECIS, CLIP_STROKE_PRECIS,DRAFT_QUALITY,DEFAULT_PITCH | FF_DONTCARE, "MS Sans Serif"); // set the font for check boxes MESS(IDC_CHKEQ, WM_SETFONT, Font, TRUE); MESS(IDC_CHKPHS,WM_SETFONT, Font, TRUE); return 1; case WM_CLOSE: EndDialog(h,0); return 0; break; } return 0; }
void main(int argc, char **argv) { const char *fxname[9]={"CHORUS","COMPRESSOR","DISTORTION","ECHO", "FLANGER","GARGLE","I3DL2REVERB","PARAMEQ","REVERB"}; HFX fx[9]={0}; // effect handles INPUT_RECORD keyin; DWORD r,buflen; printf("BASS Simple Sinewave Synth\n" "--------------------------\n"); // check the correct BASS was loaded if (HIWORD(BASS_GetVersion())!=BASSVERSION) { printf("An incorrect version of BASS.DLL was loaded"); return; } // 10ms update period BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD,10); // setup output - get latency if (!BASS_Init(-1,44100,BASS_DEVICE_LATENCY,0,NULL)) Error("Can't initialize device"); BASS_GetInfo(&info); // default buffer size = update period + 'minbuf' + 1ms extra margin BASS_SetConfig(BASS_CONFIG_BUFFER,10+info.minbuf+1); buflen=BASS_GetConfig(BASS_CONFIG_BUFFER); // if the device's output rate is unknown default to 44100 Hz if (!info.freq) info.freq=44100; // create a stream, stereo so that effects sound nice stream=BASS_StreamCreate(info.freq,2,0,(STREAMPROC*)WriteStream,0); printf("device latency: %dms\n",info.latency); printf("device minbuf: %dms\n",info.minbuf); printf("ds version: %d (effects %s)\n",info.dsver,info.dsver<8?"disabled":"enabled"); printf("press these keys to play:\n\n" " 2 3 5 6 7 9 0 =\n" " Q W ER T Y UI O P[ ]\n\n" "press -/+ to de/increase the buffer\n" "press spacebar to quit\n\n"); if (info.dsver>=8) // DX8 effects available printf("press F1-F9 to toggle effects\n\n"); printf("using a %dms buffer\r",buflen); BASS_ChannelPlay(stream,FALSE); while (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE),&keyin,1,&r)) { int key; if (keyin.EventType!=KEY_EVENT) continue; if (keyin.Event.KeyEvent.wVirtualKeyCode==VK_SPACE) break; if (keyin.Event.KeyEvent.bKeyDown) { if (keyin.Event.KeyEvent.wVirtualKeyCode==VK_SUBTRACT || keyin.Event.KeyEvent.wVirtualKeyCode==VK_ADD) { // recreate stream with smaller/larger buffer BASS_StreamFree(stream); if (keyin.Event.KeyEvent.wVirtualKeyCode==VK_SUBTRACT) BASS_SetConfig(BASS_CONFIG_BUFFER,buflen-1); // smaller buffer else BASS_SetConfig(BASS_CONFIG_BUFFER,buflen+1); // larger buffer buflen=BASS_GetConfig(BASS_CONFIG_BUFFER); printf("using a %dms buffer\t\t\r",buflen); stream=BASS_StreamCreate(info.freq,2,0,(STREAMPROC*)WriteStream,0); // set effects on the new stream for (r=0;r<9;r++) if (fx[r]) fx[r]=BASS_ChannelSetFX(stream,BASS_FX_DX8_CHORUS+r,0); BASS_ChannelPlay(stream,FALSE); } if (keyin.Event.KeyEvent.wVirtualKeyCode>=VK_F1 && keyin.Event.KeyEvent.wVirtualKeyCode<=VK_F9) { r=keyin.Event.KeyEvent.wVirtualKeyCode-VK_F1; if (fx[r]) { BASS_ChannelRemoveFX(stream,fx[r]); fx[r]=0; printf("effect %s = OFF\t\t\r",fxname[r]); } else { // set the effect, not bothering with parameters (use defaults) if (fx[r]=BASS_ChannelSetFX(stream,BASS_FX_DX8_CHORUS+r,0)) printf("effect %s = ON\t\t\r",fxname[r]); } } } for (key=0;key<KEYS;key++) if (keyin.Event.KeyEvent.wVirtualKeyCode==keys[key]) { if (keyin.Event.KeyEvent.bKeyDown && vol[key]<MAXVOL) { pos[key]=0; vol[key]=MAXVOL+DECAY/2; // start key (setting "vol" slightly higher than MAXVOL to cover any rounding-down) } else if (!keyin.Event.KeyEvent.bKeyDown && vol[key]) vol[key]-=DECAY; // trigger key fadeout break; } } BASS_Free(); }
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; }
bool BassPlayer::startRecord(const wchar_t* file) { if (m_record_params) return error(L"Already recording. First stop and start new."); int device = getMicrophoneDevice(); if (device == -1) return error(L"Microphone not found."); if (!BASS_RecordInit(device)) return error_bass(L"Can't initialize microphone.", NULL); HANDLE hfile = CreateFile(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hfile == INVALID_HANDLE_VALUE) { std::wstring message(L"Can't open file to writing :"); message.append(file); return error(message.c_str()); } // write wav header WAVEFORMATEX wf; wf.wFormatTag = WAVE_FORMAT_PCM; wf.wBitsPerSample = 16; wf.nChannels = LOWORD(m_chans_record); wf.nSamplesPerSec = m_freq_record; wf.nBlockAlign = wf.nChannels*wf.wBitsPerSample/8; wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; wf.cbSize = 0; DWORD wf_size = sizeof(WAVEFORMATEX) - sizeof(WORD); DWORD headerSize = 20 + wf_size + 8; unsigned char* header = new unsigned char [headerSize]; memcpy(header, "RIFF\0\0\0\0WAVEfmt \20\0\0\0", 20); memcpy(header+20, &wf, wf_size); memcpy(header+20+wf_size, "data\0\0\0\0", 8); DWORD written = 0; if (!WriteFile(hfile, header, headerSize, &written, NULL) || written != headerSize) { CloseHandle(hfile); DeleteFile(file); std::wstring message(L"Can't start writing :"); message.append(file); return error(message.c_str()); } m_record_params = new RecordParams; m_record_params->hfile = hfile; m_record_params->recording = TRUE; m_record = BASS_RecordStart(m_freq_record, m_chans_record, 0, MyRecordProc, m_record_params); if (!m_record) { delete m_record_params; m_record_params = NULL; CloseHandle(hfile); DeleteFile(file); return error_bass(L"Can't start recording.", NULL); } // set a volume effect on the recording channel HFX volfx = BASS_ChannelSetFX(m_record, BASS_FX_BFX_VOLUME, 0); BASS_BFX_VOLUME param; param.lChannel = 0; // global volume control param.fVolume = volume_ToFloat(m_sensivity_record); // recording volume BASS_FXSetParameters(volfx, ¶m); // apply the level change return true; }
HRESULT CBSoundBuffer::ApplyFX(TSFXType Type, float Param1, float Param2, float Param3, float Param4) { switch(Type) { case SFX_ECHO: #ifdef USE_BASS_FX if (m_EffectHandle != 0) { BASS_ChannelRemoveFX(m_Stream, m_EffectHandle); } m_EffectHandle = BASS_ChannelSetFX( m_Stream, BASS_FX_BFX_ECHO4, 0); if (m_EffectHandle != 0) { BASS_BFX_ECHO4 params; /* * try to be as close as possible to the DSFX echo, it will never be perfect though * * fDryMix = reverse of fWetDryMix (scaled from 0..100 into 0..1) * fWetMix = fWetDryMix (converted from logarithmic to linear) * fDelay = mean of fLeftDelay and fRightDelay (converted from milliseconds to seconds) * ignored = fFeedback (the BASS feedback parameter is used to create reverb) */ params.fDryMix = ((100.0f - Param1) / 100.0f); params.fWetMix = (Param1 / 100.0f); params.fFeedback = 0; params.fDelay = (Param3 + Param4) / 2.0f / 1000.0f; params.bStereo = false; params.lChannel = BASS_BFX_CHANALL; Game->LOG(0, "Echo params: Dry=%.2f Wet=%.2f Fedback=%.2f Delay=%.2f", params.fDryMix, params.fWetMix, params.fFeedback, params.fDelay); BOOL status = BASS_FXSetParameters( m_EffectHandle, (void *) ¶ms); Game->LOG(0, "Echo status=%s", (status == TRUE) ? "OK" : "ERROR"); if (status == FALSE) { Game->LOG(0, "Echo error=%d", BASS_ErrorGetCode()); } } #endif break; case SFX_REVERB: #ifdef USE_BASS_FX if (m_EffectHandle != 0) { BASS_ChannelRemoveFX(m_Stream, m_EffectHandle); } m_EffectHandle = BASS_ChannelSetFX( m_Stream, BASS_FX_BFX_ECHO4, 0); if (m_EffectHandle != 0) { BASS_BFX_ECHO4 params; /* * try to be as close as possible to the DSFX reverb, it will never be perfect though * * fDryMix = fInGain (converted from logarithmic to linear) * fWetMix = fReverbMix (converted from logarithmic to linear) multiplied ("attenuated") with fDryMix * fDelay = fReverbTime (converted from milliseconds to seconds) * ignored = fHighFreqRTRatio (no equivalent in BASS) */ params.fDryMix = pow(10.0f, (Param1 / 10.0f)); params.fWetMix = pow(10.0f, (Param2 / 10.0f)) * params.fDryMix; params.fFeedback = 0.7f; params.fDelay = ((Param3 / 1000.0f) / 10.0f); // test a different approach, where only the feedback parameter is affected by the fReverbTime params.fDryMix = 0.999f; params.fWetMix = 0.7f; params.fFeedback = 0.5f + ((Param3 / 3000.0f) * 0.2f); params.fDelay = 0.005f; params.bStereo = false; params.lChannel = BASS_BFX_CHANALL; Game->LOG(0, "Reverb params: Dry=%.2f Wet=%.2f Fedback=%.2f Delay=%.2f", params.fDryMix, params.fWetMix, params.fFeedback, params.fDelay); BOOL status = BASS_FXSetParameters( m_EffectHandle, (void *) ¶ms); Game->LOG(0, "Reverb status=%s", (status == TRUE) ? "OK" : "ERROR"); if (status == FALSE) { Game->LOG(0, "Reverb error=%d", BASS_ErrorGetCode()); } } #endif break; case SFX_REVERB_PRESET: // TODO need to check whether context is already in use #ifdef USE_LIBEFFECTS_REVERB int status; uint32_t replyCount; char replydata[8]; m_context.hInstance = NULL; m_context.boolAuxiliary = 0; m_context.boolPreset = 1; m_context.curPreset = REVERB_PRESET_LAST + 1; switch (int (Param1)) { case 0: m_context.nextPreset = REVERB_PRESET_NONE; break; case 1: m_context.nextPreset = REVERB_PRESET_SMALLROOM; break; case 2: m_context.nextPreset = REVERB_PRESET_MEDIUMROOM; break; case 3: m_context.nextPreset = REVERB_PRESET_LARGEROOM; break; case 4: m_context.nextPreset = REVERB_PRESET_MEDIUMHALL; break; case 5: m_context.nextPreset = REVERB_PRESET_LARGEHALL; break; case 6: m_context.nextPreset = REVERB_PRESET_PLATE; break; default: m_context.nextPreset = REVERB_PRESET_NONE; break; } Game->LOG(0, "====> Next preset=%d.\n", m_context.nextPreset); status = Reverb_init(&m_context); if (status != 0) { Game->LOG(0, "Reverb init error=%d", status); return S_FALSE; } m_context.config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE; m_context.InFrames32 = (LVM_INT32 *)malloc(LVREV_MAX_FRAME_SIZE * sizeof(LVM_INT32) * 2); if (m_context.InFrames32 == NULL) { Game->LOG(0, "Reverb malloc failed (1)!"); Reverb_free(&m_context); m_context.hInstance = NULL; return S_FALSE; } else { // Game->LOG(0, "Malloc inframes addr 0x%08X!", (uint32_t*) m_context.InFrames32); } m_context.OutFrames32 = (LVM_INT32 *)malloc(LVREV_MAX_FRAME_SIZE * sizeof(LVM_INT32) * 2); if (m_context.OutFrames32 == NULL) { Game->LOG(0, "Reverb malloc failed (2)!"); free(m_context.InFrames32); Reverb_free(&m_context); m_context.hInstance = NULL; return S_FALSE; } else { // Game->LOG(0, "Malloc outframes addr 0x%08X!", (uint32_t*) m_context.OutFrames32); } replyCount = sizeof(int); status = Reverb_command(&m_context, EFFECT_CMD_ENABLE, 0, NULL, &replyCount, replydata); if (status != 0) { Game->LOG(0, "Reverb command error=%d", status); free(m_context.OutFrames32); free(m_context.InFrames32); Reverb_free(&m_context); m_context.hInstance = NULL; return S_FALSE; } m_BASS_DSP_handle = BASS_ChannelSetDSP(m_Stream, DSPProc, (void *) this, 0); if (m_BASS_DSP_handle == 0) { Game->LOG(0, "BASS error: %d while adding DSP effect", BASS_ErrorGetCode()); free(m_context.OutFrames32); free(m_context.InFrames32); Reverb_free(&m_context); m_context.hInstance = NULL; return S_FALSE; } // Game->LOG(0, "Preset reverb active, ptr=0x%08X.", (uint32_t) m_pContext); Game->LOG(0, "Preset reverb active."); #endif break; default: #ifdef USE_BASS_FX if (m_EffectHandle != 0) { BASS_ChannelRemoveFX(m_Stream, m_EffectHandle); m_EffectHandle = 0; } #endif #ifdef USE_LIBEFFECTS_REVERB if (m_BASS_DSP_handle != 0) { if (BASS_ChannelRemoveDSP(m_Stream, m_BASS_DSP_handle) == FALSE) { Game->LOG(0, "BASS error: %d while removing old DSP effect", BASS_ErrorGetCode()); } m_BASS_DSP_handle = 0; } if (m_context.hInstance != NULL) { free(m_context.InFrames32); free(m_context.OutFrames32); Reverb_free(&m_context); m_context.hInstance = NULL; } #endif break; } return S_OK; }
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.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 1 // with FX flag if (!(chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_SAMPLE_LOOP|BASS_SAMPLE_FX)) && !(chan=BASS_MusicLoad(FALSE,file,0,0,BASS_SAMPLE_LOOP|BASS_MUSIC_RAMP|BASS_SAMPLE_FX,1))) { #else // without FX flag if (!(chan=BASS_StreamCreateFile(FALSE,file,0,0,BASS_SAMPLE_LOOP)) && !(chan=BASS_MusicLoad(FALSE,file,0,0,BASS_SAMPLE_LOOP|BASS_MUSIC_RAMP,1))) { #endif // 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; } MESS(10,WM_SETTEXT,0,file); { // setup the effects BASS_DX8_PARAMEQ p; fx[0]=BASS_ChannelSetFX(chan,BASS_FX_DX8_PARAMEQ,0); fx[1]=BASS_ChannelSetFX(chan,BASS_FX_DX8_PARAMEQ,0); fx[2]=BASS_ChannelSetFX(chan,BASS_FX_DX8_PARAMEQ,0); fx[3]=BASS_ChannelSetFX(chan,BASS_FX_DX8_REVERB,0); p.fGain=0; p.fBandwidth=18; p.fCenter=125; BASS_FXSetParameters(fx[0],&p); p.fCenter=1000; BASS_FXSetParameters(fx[1],&p); p.fCenter=8000; BASS_FXSetParameters(fx[2],&p); UpdateFX(0); UpdateFX(1); UpdateFX(2); UpdateFX(3); } BASS_ChannelPlay(chan,FALSE); } } break; } break; case WM_VSCROLL: if (l) { UpdateFX(GetDlgCtrlID((HWND)l)-20); } 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; // setup output - default device if (!BASS_Init(-1,44100,0,win,NULL)) { Error("Can't initialize device"); DestroyWindow(win); break; } { // check that DX8 features are available BASS_INFO bi={sizeof(bi)}; BASS_GetInfo(&bi); if (bi.dsver<8) { BASS_Free(); Error("DirectX 8 is not installed"); DestroyWindow(win); } } // initialize eq/reverb sliders MESS(20,TBM_SETRANGE,FALSE,MAKELONG(0,20)); MESS(20,TBM_SETPOS,TRUE,10); MESS(21,TBM_SETRANGE,FALSE,MAKELONG(0,20)); MESS(21,TBM_SETPOS,TRUE,10); MESS(22,TBM_SETRANGE,FALSE,MAKELONG(0,20)); MESS(22,TBM_SETPOS,TRUE,10); MESS(23,TBM_SETRANGE,FALSE,MAKELONG(0,20)); MESS(23,TBM_SETPOS,TRUE,20); return 1; case WM_DESTROY: BASS_Free(); break; } return 0; } int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow) { // check the correct BASS was loaded if (HIWORD(BASS_GetVersion())!=BASSVERSION) { MessageBox(0,"An incorrect version of BASS.DLL was loaded",0,MB_ICONERROR); return 0; } { // enable trackbar support INITCOMMONCONTROLSEX cc={sizeof(cc),ICC_BAR_CLASSES}; InitCommonControlsEx(&cc); } DialogBox(hInstance,(char*)1000,0,&dialogproc); return 0; }