CPlayer() { //return; // multi thread crash m_this = this; ZeroMemory(fx, sizeof(fx)); ZeroMemory(vol, sizeof(vol)); ZeroMemory(pos, sizeof(pos)); m_fPosition = 0.0f; m_fTempo = 120.0f; m_bPlaying = false; m_fFreqMultiply = 1.0f; m_fFreqMultiplyStep = 0.0f; // check the correct BASS was loaded if (HIWORD(BASS_GetVersion())!=BASSVERSION) { printf("An incorrect version of BASS.DLL was loaded"); return; } BASS_SetConfig(BASS_CONFIG_VISTA_TRUEPOS,0); // allows lower latency on Vista and newer BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD,10); // 10ms update period // initialize default output device (and measure latency) if (!BASS_Init(-1,44100,BASS_DEVICE_LATENCY,0,NULL)) { printf("Can't initialize device"); return; } BASS_GetInfo(&info); BASS_SetConfig(BASS_CONFIG_BUFFER,10+info.minbuf+1); // default buffer size = update period + 'minbuf' + 1ms extra margin buflen=BASS_GetConfig(BASS_CONFIG_BUFFER); if (!info.freq) info.freq=44100; // if the device's output rate is unknown default to 44100 Hz stream=BASS_StreamCreate(info.freq,2,0,(STREAMPROC*)CPlayer::_WriteStream,0); // create a stream (stereo for effects) BASS_ChannelPlay(stream,FALSE); // start it //BASS_ChannelSetFX(stream, BASS_FX_DX8_CHORUS, 0); // }
int KNMusicBackendBass::volume() const { return BASS_GetConfig(BASS_CONFIG_GVOL_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); }
void __cdecl main(int argc, char **argv) { HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); int running = 1; #ifdef WIN32 if (IsDebuggerPresent()) { // turn on floating-point exceptions unsigned int prev; _clearfp(); _controlfp_s(&prev, 0, _EM_ZERODIVIDE|_EM_INVALID); } #endif // check the correct BASS was loaded if (HIWORD(BASS_GetVersion()) != BASSVERSION) { fprintf(stderr, "An incorrect version of BASS.DLL was loaded"); return; } // set the window title SetConsoleTitle(TEXT(title_text)); // set the console buffer size static const COORD bufferSize = { 80, 50 }; SetConsoleScreenBufferSize(hOut, bufferSize); // set the console window size static const SMALL_RECT windowSize = { 0, 0, 79, 49 }; SetConsoleWindowInfo(hOut, TRUE, &windowSize); // clear the window Clear(hOut); // hide the cursor static const CONSOLE_CURSOR_INFO cursorInfo = { 100, FALSE }; SetConsoleCursorInfo(hOut, &cursorInfo); // set input mode SetConsoleMode(hIn, 0); // 10ms update period const DWORD STREAM_UPDATE_PERIOD = 10; BASS_SetConfig(BASS_CONFIG_UPDATEPERIOD, STREAM_UPDATE_PERIOD); // initialize BASS sound library const DWORD STREAM_FREQUENCY = 48000; if (!BASS_Init(-1, STREAM_FREQUENCY, BASS_DEVICE_LATENCY, 0, NULL)) Error("Can't initialize device"); // get device info BASS_GetInfo(&info); // if the device's output rate is unknown default to stream frequency if (!info.freq) info.freq = STREAM_FREQUENCY; // debug print info DebugPrint("frequency: %d (min %d, max %d)\n", info.freq, info.minrate, info.maxrate); DebugPrint("device latency: %dms\n", info.latency); DebugPrint("device minbuf: %dms\n", info.minbuf); DebugPrint("ds version: %d (effects %s)\n", info.dsver, info.dsver < 8 ? "disabled" : "enabled"); // default buffer size = update period + 'minbuf' + 1ms extra margin BASS_SetConfig(BASS_CONFIG_BUFFER, STREAM_UPDATE_PERIOD + info.minbuf + 1); DebugPrint("using a %dms buffer\r", BASS_GetConfig(BASS_CONFIG_BUFFER)); // create a stream, stereo so that effects sound nice stream = BASS_StreamCreate(info.freq, 2, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream, 0); // set channel to apply effects fx_channel = stream; #ifdef BANDLIMITED_SAWTOOTH // initialize bandlimited sawtooth tables InitSawtooth(); #endif // initialize waves InitWave(); // enable the first oscillator osc_config[0].enable = true; // reset all controllers Control::ResetAll(); // start playing the audio stream BASS_ChannelPlay(stream, FALSE); // get the number of midi devices UINT midiInDevs = Midi::Input::GetNumDevices(); DebugPrint("MIDI input devices: %d\n", midiInDevs); // print device names for (UINT i = 0; i < midiInDevs; ++i) { MIDIINCAPS midiInCaps; if (Midi::Input::GetDeviceCaps(i, midiInCaps) == 0) { DebugPrint("%d: %s\n", i, midiInCaps.szPname); } } // if there are any devices available... if (midiInDevs > 0) { // open and start midi input // TO DO: select device number via a configuration setting Midi::Input::Open(0); Midi::Input::Start(); } // initialize to middle c note_most_recent = 60; voice_note[voice_most_recent] = unsigned char(note_most_recent); DisplaySpectrumAnalyzer displaySpectrumAnalyzer; DisplayKeyVolumeEnvelope displayKeyVolumeEnvelope; DisplayOscillatorWaveform displayOscillatorWaveform; DisplayOscillatorFrequency displayOscillatorFrequency; DisplayLowFrequencyOscillator displayLowFrequencyOscillator; DisplayFilterFrequency displayFilterFrequency; // initialize spectrum analyzer displaySpectrumAnalyzer.Init(stream, info); // initialize key display displayKeyVolumeEnvelope.Init(hOut); // show output scale and key octave PrintOutputScale(hOut); PrintKeyOctave(hOut); PrintGoToEffects(hOut); PrintAntialias(hOut); // show main page Menu::SetActivePage(hOut, Menu::PAGE_MAIN); while (running) { // if there are any pending input events... DWORD numEvents = 0; while (GetNumberOfConsoleInputEvents(hIn, &numEvents) && numEvents > 0) { // get the next input event INPUT_RECORD keyin; ReadConsoleInput(hIn, &keyin, 1, &numEvents); if (keyin.EventType == KEY_EVENT) { // handle interface keys if (keyin.Event.KeyEvent.bKeyDown) { WORD code = keyin.Event.KeyEvent.wVirtualKeyCode; DWORD modifiers = keyin.Event.KeyEvent.dwControlKeyState; if (code == VK_ESCAPE) { running = 0; break; } else if (code == VK_OEM_MINUS || code == VK_SUBTRACT) { Menu::UpdatePercentageProperty(output_scale, -1, modifiers, 0, 4); PrintOutputScale(hOut); } else if (code == VK_OEM_PLUS || code == VK_ADD) { Menu::UpdatePercentageProperty(output_scale, +1, modifiers, 0, 4); PrintOutputScale(hOut); } else if (code == VK_OEM_4) // '[' { if (keyboard_octave > 1) { for (int k = 0; k < KEYS; ++k) { if (key_down[k]) NoteOff(k + keyboard_octave * 12); } --keyboard_octave; for (int k = 0; k < KEYS; ++k) { if (key_down[k]) NoteOn(k + keyboard_octave * 12); } PrintKeyOctave(hOut); } } else if (code == VK_OEM_6) // ']' { if (keyboard_octave < 9) { for (int k = 0; k < KEYS; ++k) { if (key_down[k]) NoteOff(k + keyboard_octave * 12); } ++keyboard_octave; for (int k = 0; k < KEYS; ++k) { if (key_down[k]) NoteOn(k + keyboard_octave * 12); } PrintKeyOctave(hOut); } } else if (code == VK_F12) { use_antialias = !use_antialias; PrintAntialias(hOut); } else if (code >= VK_F1 && code < VK_F10) { Menu::SetActiveMenu(hOut, code - VK_F1); } else if (code == VK_F10) { PrintGoToEffects(hOut); Menu::SetActivePage(hOut, Menu::PAGE_MAIN); } else if (code == VK_F11) { PrintGoToMain(hOut); Menu::SetActivePage(hOut, Menu::PAGE_FX); } else if (code == VK_TAB) { if (modifiers & SHIFT_PRESSED) Menu::PrevMenu(hOut); else Menu::NextMenu(hOut); } else if (code == VK_UP || code == VK_DOWN || code == VK_RIGHT || code == VK_LEFT) { Menu::Handler(hOut, code, modifiers); } } // handle note keys for (int k = 0; k < KEYS; k++) { if (keyin.Event.KeyEvent.wVirtualKeyCode == keys[k]) { // key down bool down = (keyin.Event.KeyEvent.bKeyDown != 0); // if key down state changed... if (key_down[k] != down) { // update state key_down[k] = down; // if pressing the key if (down) { // note on NoteOn(k + keyboard_octave * 12); } else { // note off NoteOff(k + keyboard_octave * 12); } } break; } } } } // center frequency of the zeroth semitone band // (one octave down from the lowest key) float const freq_min = powf(2, float(keyboard_octave - 6)) * middle_c_frequency; // update the spectrum analyzer display displaySpectrumAnalyzer.Update(hOut, stream, info, freq_min); // update note key volume envelope display displayKeyVolumeEnvelope.Update(hOut); if (Menu::active_page == Menu::PAGE_MAIN) { // update the oscillator waveform display displayOscillatorWaveform.Update(hOut, info, voice_most_recent); // update the oscillator frequency displays for (int o = 0; o < NUM_OSCILLATORS; ++o) { if (osc_config[o].enable) displayOscillatorFrequency.Update(hOut, voice_most_recent, o); } // update the low-frequency oscillator display displayLowFrequencyOscillator.Update(hOut); // update the filter frequency display if (flt_config.enable) displayFilterFrequency.Update(hOut, voice_most_recent); } // show CPU usage PrintConsole(hOut, { 73, 49 }, "%6.2f%%", BASS_GetCPU()); // sleep for 1/60th of second Sleep(16); } if (midiInDevs) { // stop and close midi input Midi::Input::Stop(); Midi::Input::Close(); } // clean up spectrum analyzer displaySpectrumAnalyzer.Cleanup(stream); // clear the window Clear(hOut); BASS_Free(); }
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(); }
BYTE CBSoundMgr::GetMasterVolumePercent() { DWORD val = BASS_GetConfig(BASS_CONFIG_GVOL_STREAM); return (float)val / 10000.0f * 100.0f; }