📄 snd_wave_mixer.cpp
字号:
// If we are terminating this wave prematurely, then make sure we detect the limit
if ( m_forcedEndSample )
{
// How many total input samples will we need?
int samplesRequired = (int)(sampleCount * rate);
// will this hit the end?
if ( m_sample + samplesRequired >= m_forcedEndSample )
{
// yes, mark finished and truncate the sample request
m_finished = true;
sampleCount = (int)( (m_forcedEndSample - m_sample) / rate );
}
}
while ( sampleCount > 0 )
{
bool advanceSample = true;
int availableSamples, outputSampleCount;
char *pData = NULL;
// compute number of input samples required
double end = m_sample + rate * sampleCount;
int inputSampleCount = (int)(ceil(end) - floor(m_sample));
// ask the source for the data
char copyBuf[AUDIOSOURCE_COPYBUF_SIZE];
if ( m_delaySamples > 0 )
{
int num_zero_samples = min( m_delaySamples, inputSampleCount );
// Decrement data amount
m_delaySamples -= num_zero_samples;
int sampleSize = m_pData->Source().SampleSize();
int readBytes = sampleSize * num_zero_samples;
Assert( readBytes <= sizeof( copyBuf ) );
pData = ©Buf[0];
// Now copy in some zeroes
memset( pData, 0, readBytes );
availableSamples = num_zero_samples;
advanceSample = false;
}
else
{
availableSamples = GetOutputData((void**)&pData, inputSampleCount, copyBuf);
}
// none available, bail out
if ( !availableSamples )
{
break;
}
double sampleFraction = m_sample - floor(m_sample);
if ( availableSamples < inputSampleCount )
{
// How many samples are there given the number of input samples and the rate.
outputSampleCount = (int)ceil((availableSamples - sampleFraction) / rate);
}
else
{
outputSampleCount = sampleCount;
}
// Verify that we won't get a buffer overrun.
assert(floor(sampleFraction + rate * (outputSampleCount-1)) <= availableSamples);
if ( advanceSample )
{
m_sample += outputSampleCount * rate;
}
outputOffset += outputSampleCount;
sampleCount -= outputSampleCount;
}
// Did we run out of samples? if so, mark finished
if ( sampleCount > 0 )
{
m_finished = true;
}
// total number of samples mixed !!! at the output clock rate !!!
return outputOffset - startingOffset;
}
//-----------------------------------------------------------------------------
// Purpose: The device calls this to request data. The mixer must provide the
// full amount of samples or have silence in its output stream.
// Mix channel to all active paintbuffers.
// NOTE: cannot be called consecutively to mix into multiple paintbuffers!
// Input : *pDevice - requesting device
// sampleCount - number of samples at the output rate
// outputRate - sampling rate of the request
// Output : Returns true to keep mixing, false to delete this mixer
//-----------------------------------------------------------------------------
int CAudioMixerWave::MixDataToDevice( IAudioDevice *pDevice, channel_t *pChannel, int sampleCount, int outputRate, int outputOffset )
{
// shouldn't be playing this if finished, but return if we are
if ( m_finished )
return 0;
// save this to compute total output
int startingOffset = outputOffset;
float inputRate = (pChannel->pitch * m_pData->Source().SampleRate());
float rate = inputRate / outputRate;
// If we are terminating this wave prematurely, then make sure we detect the limit
if ( m_forcedEndSample )
{
// How many total input samples will we need?
int samplesRequired = (int)(sampleCount * rate);
// will this hit the end?
if ( m_sample + samplesRequired >= m_forcedEndSample )
{
// yes, mark finished and truncate the sample request
m_finished = true;
sampleCount = (int)( (m_forcedEndSample - m_sample) / rate );
}
}
while ( sampleCount > 0 )
{
bool advanceSample = true;
int availableSamples, outputSampleCount;
char *pData = NULL;
// compute number of input samples required
double end = m_sample + rate * sampleCount;
int inputSampleCount = (int)(ceil(end) - floor(m_sample));
// ask the source for the data
char copyBuf[AUDIOSOURCE_COPYBUF_SIZE];
if ( m_delaySamples > 0 )
{
int num_zero_samples = min( m_delaySamples, inputSampleCount );
// Decrement data amount
m_delaySamples -= num_zero_samples;
int sampleSize = m_pData->Source().SampleSize();
int readBytes = sampleSize * num_zero_samples;
Assert( readBytes <= sizeof( copyBuf ) );
pData = ©Buf[0];
// Now copy in some zeroes
memset( pData, 0, readBytes );
availableSamples = num_zero_samples;
advanceSample = false;
}
else
{
availableSamples = GetOutputData((void**)&pData, inputSampleCount, copyBuf);
}
// none available, bail out
if ( !availableSamples )
{
break;
}
double sampleFraction = m_sample - floor(m_sample);
if ( availableSamples < inputSampleCount )
{
// How many samples are there given the number of input samples and the rate.
outputSampleCount = (int)ceil((availableSamples - sampleFraction) / rate);
}
else
{
outputSampleCount = sampleCount;
}
// Verify that we won't get a buffer overrun.
assert(floor(sampleFraction + rate * (outputSampleCount-1)) <= availableSamples);
// mix this data to all active paintbuffers
int i, j;
// save current paintbuffer
j = MIX_GetCurrentPaintbufferIndex();
for (i = 0 ; i < CPAINTBUFFERS; i++)
{
if (paintbuffers[i].factive)
{
// mix chan into all active paintbuffers
MIX_SetCurrentPaintbuffer(i);
Mix(
pDevice, // Device.
pChannel, // Channel.
pData, // Input buffer.
outputOffset, // Output position.
FIX_FLOAT(sampleFraction), // Iterators.
FIX_FLOAT(rate),
outputSampleCount,
0
);
}
}
MIX_SetCurrentPaintbuffer(j);
if ( advanceSample )
{
m_sample += outputSampleCount * rate;
}
outputOffset += outputSampleCount;
sampleCount -= outputSampleCount;
}
// Did we run out of samples? if so, mark finished
if ( sampleCount > 0 )
{
m_finished = true;
}
// total number of samples mixed !!! at the output clock rate !!!
return outputOffset - startingOffset;
}
bool CAudioMixerWave::ShouldContinueMixing( void )
{
return !m_finished;
}
float CAudioMixerWave::ModifyPitch( float pitch )
{
return pitch;
}
float CAudioMixerWave::GetVolumeScale( void )
{
return 1.0f;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -