Example #1
0
	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);
		//
	}
Example #2
0
int KNMusicBackendBass::volume() const
{
    return BASS_GetConfig(BASS_CONFIG_GVOL_STREAM);
}
Example #3
0
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);
}
Example #4
0
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();
}
Example #5
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();
}
BYTE CBSoundMgr::GetMasterVolumePercent()
{
	DWORD val = BASS_GetConfig(BASS_CONFIG_GVOL_STREAM);
	return (float)val / 10000.0f * 100.0f;
}