コード例 #1
0
	waveout_stream_raii( commandlineflags & flags )
		: waveout(NULL)
		, num_channels(0)
		, num_chunks(0)
		, frames_per_chunk(0)
		, bytes_per_chunk(0)
	{
		if ( flags.buffer == default_high ) {
			flags.buffer = 150;
		} else if ( flags.buffer == default_low ) {
			flags.buffer = 50;
		}
		if ( flags.period == default_high ) {
			flags.period = 30;
		} else if ( flags.period == default_low ) {
			flags.period = 10;
		}
		flags.apply_default_buffer_sizes();
		WAVEFORMATEX wfx;
		ZeroMemory( &wfx, sizeof( wfx ) );
		wfx.wFormatTag = flags.use_float ? WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM;
		wfx.nChannels = flags.channels;
		wfx.nSamplesPerSec = flags.samplerate;
		wfx.wBitsPerSample = flags.use_float ? 32 : 16;
		wfx.nBlockAlign = ( wfx.wBitsPerSample / 8 ) * wfx.nChannels;
		wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
		wfx.cbSize = 0;
		waveOutOpen( &waveout, flags.device == -1 ? WAVE_MAPPER : flags.device, &wfx, 0, 0, CALLBACK_NULL );
		num_channels = flags.channels;
		std::size_t frames_per_buffer = flags.samplerate * flags.buffer / 1000;
		num_chunks = ( flags.buffer + flags.period - 1 ) / flags.period;
		if ( num_chunks < 2 ) {
			num_chunks = 2;
		}
		frames_per_chunk = ( frames_per_buffer + num_chunks - 1 ) / num_chunks;
		bytes_per_chunk = wfx.nBlockAlign * frames_per_chunk;
		waveheaders.resize( num_chunks );
		wavebuffers.resize( num_chunks );
		for ( std::size_t i = 0; i < num_chunks; ++i ) {
			wavebuffers[i].resize( bytes_per_chunk );
			waveheaders[i] = WAVEHDR();
			waveheaders[i].lpData = wavebuffers[i].data();
			waveheaders[i].dwBufferLength = static_cast<DWORD>( wavebuffers[i].size() );
			waveheaders[i].dwFlags = 0;
			waveOutPrepareHeader( waveout, &waveheaders[i], sizeof( WAVEHDR ) );
		}
	}
コード例 #2
0
ファイル: openmpt123_portaudio.hpp プロジェクト: kode54/Cog
	portaudio_stream_blocking_raii( commandlineflags & flags, std::ostream & log )
		: portaudio_raii(flags.verbose, log)
		, stream(NULL)
		, interleaved(false)
		, channels(flags.channels)
	{
		PaStreamParameters streamparameters;
		std::memset( &streamparameters, 0, sizeof(PaStreamParameters) );
		std::istringstream device_string( flags.device );
		int device = -1;
		device_string >> device;
		streamparameters.device = ( device == -1 ) ? Pa_GetDefaultOutputDevice() : device;
		streamparameters.channelCount = flags.channels;
		streamparameters.sampleFormat = ( flags.use_float ? paFloat32 : paInt16 ) | paNonInterleaved;
		if ( flags.buffer == default_high ) {
			streamparameters.suggestedLatency = Pa_GetDeviceInfo( streamparameters.device )->defaultHighOutputLatency;
			flags.buffer = static_cast<std::int32_t>( Pa_GetDeviceInfo( streamparameters.device )->defaultHighOutputLatency * 1000.0 );
		} else if ( flags.buffer == default_low ) {
			streamparameters.suggestedLatency = Pa_GetDeviceInfo( streamparameters.device )->defaultLowOutputLatency;
			flags.buffer = static_cast<std::int32_t>( Pa_GetDeviceInfo( streamparameters.device )->defaultLowOutputLatency * 1000.0 );
		} else {
			streamparameters.suggestedLatency = flags.buffer * 0.001;
		}
		unsigned long framesperbuffer = 0;
		if ( flags.mode != ModeUI ) {
			framesperbuffer = paFramesPerBufferUnspecified;
			flags.period = 50;
			flags.period = std::min<std::int32_t>( flags.period, flags.buffer / 3 );
		} else if ( flags.period == default_high ) {
			framesperbuffer = paFramesPerBufferUnspecified;
			flags.period = 50;
			flags.period = std::min<std::int32_t>( flags.period, flags.buffer / 3 );
		} else if ( flags.period == default_low ) {
			framesperbuffer = paFramesPerBufferUnspecified;
			flags.period = 10;
			flags.period = std::min<std::int32_t>( flags.period, flags.buffer / 3 );
		} else {
			framesperbuffer = flags.period * flags.samplerate / 1000;
		}
		if ( flags.period <= 0 ) {
			flags.period = 1;
		}
		flags.apply_default_buffer_sizes();
		if ( flags.verbose ) {
			log << "PortAudio:" << std::endl;
			log << " device: "
				<< streamparameters.device
				<< " [ " << Pa_GetHostApiInfo( Pa_GetDeviceInfo( streamparameters.device )->hostApi )->name << " / " << Pa_GetDeviceInfo( streamparameters.device )->name << " ] "
				<< std::endl;
			log << " low latency: " << Pa_GetDeviceInfo( streamparameters.device )->defaultLowOutputLatency << std::endl;
			log << " high latency: " << Pa_GetDeviceInfo( streamparameters.device )->defaultHighOutputLatency << std::endl;
			log << " suggested latency: " << streamparameters.suggestedLatency << std::endl;
			log << " frames per buffer: " << framesperbuffer << std::endl;
			log << " ui redraw: " << flags.period << std::endl;
		}
		PaError e = PaError();
		e = Pa_OpenStream( &stream, NULL, &streamparameters, flags.samplerate, framesperbuffer, ( flags.dither > 0 ) ? paNoFlag : paDitherOff, NULL, NULL );
		if ( e != paNoError ) {
			// Non-interleaved failed, try interleaved next.
			// This might help broken portaudio on MacOS X.
			streamparameters.sampleFormat &= ~paNonInterleaved;
			e = Pa_OpenStream( &stream, NULL, &streamparameters, flags.samplerate, framesperbuffer, ( flags.dither > 0 ) ? paNoFlag : paDitherOff, NULL, NULL );
			if ( e == paNoError ) {
				interleaved = true;
			}
			check_portaudio_error( e );
		}
		check_portaudio_error( Pa_StartStream( stream ) );
		if ( flags.verbose ) {
			log << " channels: " << streamparameters.channelCount << std::endl;
			log << " sampleformat: " << ( ( ( streamparameters.sampleFormat & ~paNonInterleaved ) == paFloat32 ) ? "paFloat32" : "paInt16" ) << std::endl;
			log << " latency: " << Pa_GetStreamInfo( stream )->outputLatency << std::endl;
			log << " samplerate: " << Pa_GetStreamInfo( stream )->sampleRate << std::endl;
			log << std::endl;
		}
	}