Exemple #1
0
bool SampleBuffer::play( sampleFrame * _ab, handleState * _state,
					const fpp_t _frames,
					const float _freq,
					const LoopMode _loopmode )
{
	m_varLock.lockForRead();

	f_cnt_t startFrame = m_startFrame;
	f_cnt_t endFrame = m_endFrame;
	f_cnt_t loopStartFrame = m_loopStartFrame;
	f_cnt_t loopEndFrame = m_loopEndFrame;

	if( endFrame == 0 || _frames == 0 )
	{
		m_varLock.unlock();
		return false;
	}

	// variable for determining if we should currently be playing backwards in a ping-pong loop
	bool is_backwards = _state->isBackwards();

	const double freq_factor = (double) _freq / (double) m_frequency *
		m_sampleRate / engine::mixer()->processingSampleRate();

	// calculate how many frames we have in requested pitch
	const f_cnt_t total_frames_for_current_pitch = static_cast<f_cnt_t>( (
						endFrame - startFrame ) /
								freq_factor );

	if( total_frames_for_current_pitch == 0 )
	{
		m_varLock.unlock();
		return false;
	}


	// this holds the number of the first frame to play
	f_cnt_t play_frame = _state->m_frameIndex;

	if( play_frame < startFrame )
	{
		play_frame = startFrame;
	}

	if( _loopmode == LoopOff )
	{
		if( play_frame >= endFrame )
		{
			m_varLock.unlock();
			return false;
		}

		if( ( endFrame - play_frame ) / freq_factor == 0 ) return false;
	}

	else if( _loopmode == LoopOn )
	{
		play_frame = getLoopedIndex( play_frame, loopStartFrame, loopEndFrame );
	}

	else
	{
		play_frame = getPingPongIndex( play_frame, loopStartFrame, loopEndFrame );
	}

	f_cnt_t fragment_size = (f_cnt_t)( _frames * freq_factor ) + MARGIN[ _state->interpolationMode() ];

	sampleFrame * tmp = NULL;

	// check whether we have to change pitch...
	if( freq_factor != 1.0 || _state->m_varyingPitch )
	{
		SRC_DATA src_data;
		// Generate output
		src_data.data_in =
			getSampleFragment( play_frame, fragment_size, _loopmode, &tmp, &is_backwards,
			loopStartFrame, loopEndFrame, endFrame )[0];
		src_data.data_out = _ab[0];
		src_data.input_frames = fragment_size;
		src_data.output_frames = _frames;
		src_data.src_ratio = 1.0 / freq_factor;
		src_data.end_of_input = 0;
		int error = src_process( _state->m_resamplingData,
								&src_data );
		if( error )
		{
			printf( "SampleBuffer: error while resampling: %s\n",
							src_strerror( error ) );
		}
		if( src_data.output_frames_gen > _frames )
		{
			printf( "SampleBuffer: not enough frames: %ld / %d\n",
					src_data.output_frames_gen, _frames );
		}
		// Advance
		switch( _loopmode )
		{
			case LoopOff:
				play_frame += src_data.input_frames_used;
				break;
			case LoopOn:
				play_frame += src_data.input_frames_used;
				play_frame = getLoopedIndex( play_frame, loopStartFrame, loopEndFrame );
				break;
			case LoopPingPong:
			{
				f_cnt_t left = src_data.input_frames_used;
				if( _state->isBackwards() )
				{
					play_frame -= src_data.input_frames_used;
					if( play_frame < loopStartFrame )
					{
						left -= ( loopStartFrame - play_frame );
						play_frame = loopStartFrame;
					}
					else left = 0;
				}
				play_frame += left;
				play_frame = getPingPongIndex( play_frame, loopStartFrame, loopEndFrame  );
				break;
			}
		}
	}
	else
	{
		// we don't have to pitch, so we just copy the sample-data
		// as is into pitched-copy-buffer

		// Generate output
		memcpy( _ab,
			getSampleFragment( play_frame, _frames, _loopmode, &tmp, &is_backwards,
						loopStartFrame, loopEndFrame, endFrame ),
						_frames * BYTES_PER_FRAME );
		// Advance
		switch( _loopmode )
		{
			case LoopOff:
				play_frame += _frames;
				break;
			case LoopOn:
				play_frame += _frames;
				play_frame = getLoopedIndex( play_frame, loopStartFrame, loopEndFrame  );
				break;
			case LoopPingPong:
			{
				f_cnt_t left = _frames;
				if( _state->isBackwards() )
				{
					play_frame -= _frames;
					if( play_frame < loopStartFrame )
					{
						left -= ( loopStartFrame - play_frame );
						play_frame = loopStartFrame;
					}
					else left = 0;
				}
				play_frame += left;
				play_frame = getPingPongIndex( play_frame, loopStartFrame, loopEndFrame  );
				break;
			}
		}
	}

	if( tmp != NULL ) 
	{
		MM_FREE( tmp );
	}

	_state->setBackwards( is_backwards );
	_state->setFrameIndex( play_frame );

	for( fpp_t i = 0; i < _frames; ++i )
	{
		_ab[i][0] *= m_amplification;
		_ab[i][1] *= m_amplification;
	}

	m_varLock.unlock();
	return true;
}
bool SampleBuffer::play( sampleFrame * _ab, handleState * _state,
					const fpp_t _frames,
					const float _freq,
					const bool _looped )
{
	QMutexLocker ml( &m_varLock );

	engine::mixer()->clearAudioBuffer( _ab, _frames );

	if( m_endFrame == 0 || _frames == 0 )
	{
		return false;
	}

	const double freq_factor = (double) _freq / (double) m_frequency *
		m_sampleRate / engine::mixer()->processingSampleRate();

	// calculate how many frames we have in requested pitch
	const f_cnt_t total_frames_for_current_pitch = static_cast<f_cnt_t>( (
						m_endFrame - m_startFrame ) /
								freq_factor );
	if( total_frames_for_current_pitch == 0 )
	{
		return false;
	}

	// this holds the number of the first frame to play
	f_cnt_t play_frame = _state->m_frameIndex;
	if( play_frame < m_startFrame )
	{
		play_frame = m_startFrame;
	}

	// this holds the number of remaining frames in current loop
	f_cnt_t frames_for_loop;
	if( _looped )
	{
		play_frame = getLoopedIndex( play_frame );
		frames_for_loop = static_cast<f_cnt_t>(
					( m_loopEndFrame - play_frame ) /
								freq_factor );
	}
	else
	{
		if( play_frame >= m_endFrame )
		{
			return false;
		}
		frames_for_loop = static_cast<f_cnt_t>(
					( m_endFrame - play_frame ) /
								freq_factor );
		if( frames_for_loop == 0 )
		{
			return false;
		}
	}

	sampleFrame * tmp = NULL;

	// check whether we have to change pitch...
	if( freq_factor != 1.0 || _state->m_varyingPitch )
	{
		SRC_DATA src_data;
		// Generate output
		const f_cnt_t margin = 64;
		f_cnt_t fragment_size = (f_cnt_t)( _frames * freq_factor )
								+ margin;
		src_data.data_in = getSampleFragment( play_frame,
					fragment_size, _looped, &tmp )[0];
		src_data.data_out = _ab[0];
		src_data.input_frames = fragment_size;
		src_data.output_frames = _frames;
		src_data.src_ratio = 1.0 / freq_factor;
		src_data.end_of_input = 0;
		int error = src_process( _state->m_resamplingData,
								&src_data );
		if( error )
		{
			printf( "SampleBuffer: error while resampling: %s\n",
							src_strerror( error ) );
		}
		if( src_data.output_frames_gen > _frames )
		{
			printf( "SampleBuffer: not enough frames: %ld / %d\n",
					src_data.output_frames_gen, _frames );
		}
		// Advance
		play_frame += src_data.input_frames_used;
		if( _looped )
		{
			play_frame = getLoopedIndex( play_frame );
		}
	}
	else
	{
		// we don't have to pitch, so we just copy the sample-data
		// as is into pitched-copy-buffer

		// Generate output
		memcpy( _ab,
			getSampleFragment( play_frame, _frames, _looped, &tmp ),
						_frames * BYTES_PER_FRAME );
		// Advance
		play_frame += _frames;
		if( _looped )
		{
			play_frame = getLoopedIndex( play_frame );
		}
	}

	delete[] tmp;

	_state->m_frameIndex = play_frame;

	return true;

}