예제 #1
0
void XAudio2_Output::setThrottle( unsigned short throttle )
{
	if( !initialized || failed ) return;

	if( throttle == 0 ) throttle = 100;
	HRESULT hr = sVoice->SetFrequencyRatio( (float)throttle / 100.0f );
	ASSERT( hr == S_OK );
}
예제 #2
0
	virtual const char* open( void * hwnd, unsigned sample_rate, unsigned nch, unsigned max_samples_per_frame, unsigned num_frames )
	{
		this->hwnd = hwnd;
		this->sample_rate = sample_rate;
		this->nch = nch;
		this->max_samples_per_frame = max_samples_per_frame;
		this->num_frames = num_frames;

#ifdef HAVE_KS_HEADERS
		WAVEFORMATEXTENSIBLE wfx;
		wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
		wfx.Format.nChannels = nch; //1;
		wfx.Format.nSamplesPerSec = sample_rate;
		wfx.Format.nBlockAlign = 2 * nch; //2;
		wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign;
		wfx.Format.wBitsPerSample = 16;
		wfx.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX);
		wfx.Samples.wValidBitsPerSample = 16;
		wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
		wfx.dwChannelMask = nch == 2 ? KSAUDIO_SPEAKER_STEREO : KSAUDIO_SPEAKER_MONO;
#else
		WAVEFORMATEX wfx;
		wfx.wFormatTag = WAVE_FORMAT_PCM;
		wfx.nChannels = nch; //1;
		wfx.nSamplesPerSec = sample_rate;
		wfx.nBlockAlign = 2 * nch; //2;
		wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
		wfx.wBitsPerSample = 16;
		wfx.cbSize = 0;
#endif
        HRESULT hr = XAudio2Create( &xaud, 0 );
		if (FAILED(hr)) return "Creating XAudio2 interface";
		hr = xaud->CreateMasteringVoice(
			&mVoice,
			nch,
			sample_rate,
			0,
			NULL,
			NULL );
		if (FAILED(hr)) return "Creating XAudio2 mastering voice";
		hr = xaud->CreateSourceVoice( &sVoice, &wfx, 0, 4.0f, &notify );
		if (FAILED(hr)) return "Creating XAudio2 source voice";
		hr = sVoice->Start( 0 );
		if (FAILED(hr)) return "Starting XAudio2 voice";
		hr = sVoice->SetFrequencyRatio((float)1.0f);
		if (FAILED(hr)) return "Setting XAudio2 voice frequency ratio";
		buffered_count = 0;
		buffer_read_cursor = 0;
		buffer_write_cursor = 0;
		samples_played = 0;
		sample_buffer = new int16_t[ max_samples_per_frame * num_frames ];
		samples_in_buffer = new UINT64[ num_frames ];
		memset( samples_in_buffer, 0, sizeof( UINT64 ) * num_frames );
		return NULL;
	}
예제 #3
0
	virtual const char* set_ratio( double ratio )
	{
		if ( FAILED( sVoice->SetFrequencyRatio( ratio ) ) ) return "setting ratio";
		return 0;
	}
예제 #4
0
//-----------------------------------------------------------------------------
// Perform per-frame update of audio
//-----------------------------------------------------------------------------
HRESULT UpdateAudio( float fElapsedTime )
{
    if( !g_audioState.bInitialized )
        return S_FALSE;

    if( g_audioState.nFrameToApply3DAudio == 0 )
    {
        // Calculate listener orientation in x-z plane
        if( g_audioState.vListenerPos.x != g_audioState.listener.Position.x
            || g_audioState.vListenerPos.z != g_audioState.listener.Position.z )
        {
            XMVECTOR v1 = XMLoadFloat3( &g_audioState.vListenerPos );
            XMVECTOR v2 = XMVectorSet( g_audioState.listener.Position.x, g_audioState.listener.Position.y, g_audioState.listener.Position.z, 0.f  );

            XMVECTOR vDelta = v1 - v2;

            g_audioState.fListenerAngle = float( atan2( XMVectorGetX( vDelta ), XMVectorGetZ( vDelta ) ) );

            vDelta = XMVectorSetY( vDelta, 0.f );
            vDelta = XMVector3Normalize( vDelta );

            XMFLOAT3 tmp;
            XMStoreFloat3( &tmp, vDelta );

            g_audioState.listener.OrientFront.x = tmp.x;
            g_audioState.listener.OrientFront.y = 0.f;
            g_audioState.listener.OrientFront.z = tmp.z;
        }

        if (g_audioState.fUseListenerCone)
        {
            g_audioState.listener.pCone = (X3DAUDIO_CONE*)&Listener_DirectionalCone;
        }
        else
        {
            g_audioState.listener.pCone = nullptr;
        }
        if (g_audioState.fUseInnerRadius)
        {
            g_audioState.emitter.InnerRadius = 2.0f;
            g_audioState.emitter.InnerRadiusAngle = X3DAUDIO_PI/4.0f;
        }
        else
        {
            g_audioState.emitter.InnerRadius = 0.0f;
            g_audioState.emitter.InnerRadiusAngle = 0.0f;
        }

        if( fElapsedTime > 0 )
        {
            XMVECTOR v1 = XMLoadFloat3( &g_audioState.vListenerPos );
            XMVECTOR v2 = XMVectorSet( g_audioState.listener.Position.x, g_audioState.listener.Position.y, g_audioState.listener.Position.z, 0 );

            XMVECTOR lVelocity = ( v1 - v2 ) / fElapsedTime;
            g_audioState.listener.Position.x = g_audioState.vListenerPos.x;
            g_audioState.listener.Position.y = g_audioState.vListenerPos.y;
            g_audioState.listener.Position.z = g_audioState.vListenerPos.z;

            XMFLOAT3 tmp;
            XMStoreFloat3( &tmp, lVelocity );
            g_audioState.listener.Velocity.x = tmp.x;
            g_audioState.listener.Velocity.y = tmp.y;
            g_audioState.listener.Velocity.z = tmp.z;

            v1 = XMLoadFloat3( &g_audioState.vEmitterPos );
            v2 = XMVectorSet( g_audioState.emitter.Position.x, g_audioState.emitter.Position.y, g_audioState.emitter.Position.z, 0.f );

            XMVECTOR eVelocity = ( v1 - v2 ) / fElapsedTime;
            g_audioState.emitter.Position.x = g_audioState.vEmitterPos.x;
            g_audioState.emitter.Position.y = g_audioState.vEmitterPos.y;
            g_audioState.emitter.Position.z = g_audioState.vEmitterPos.z;

            XMStoreFloat3( &tmp, eVelocity );
            g_audioState.emitter.Velocity.x = tmp.x;
            g_audioState.emitter.Velocity.y = tmp.y;
            g_audioState.emitter.Velocity.z = tmp.z;
        }

        DWORD dwCalcFlags = X3DAUDIO_CALCULATE_MATRIX | X3DAUDIO_CALCULATE_DOPPLER
            | X3DAUDIO_CALCULATE_LPF_DIRECT | X3DAUDIO_CALCULATE_LPF_REVERB
            | X3DAUDIO_CALCULATE_REVERB;
        if (g_audioState.fUseRedirectToLFE)
        {
            // On devices with an LFE channel, allow the mono source data
            // to be routed to the LFE destination channel.
            dwCalcFlags |= X3DAUDIO_CALCULATE_REDIRECT_TO_LFE;
        }

        X3DAudioCalculate( g_audioState.x3DInstance, &g_audioState.listener, &g_audioState.emitter, dwCalcFlags,
                           &g_audioState.dspSettings );

        IXAudio2SourceVoice* voice = g_audioState.pSourceVoice;
        if( voice )
        {
            // Apply X3DAudio generated DSP settings to XAudio2
            voice->SetFrequencyRatio( g_audioState.dspSettings.DopplerFactor );
            voice->SetOutputMatrix( g_audioState.pMasteringVoice, INPUTCHANNELS, g_audioState.nChannels,
                                    g_audioState.matrixCoefficients );

            voice->SetOutputMatrix(g_audioState.pSubmixVoice, 1, 1, &g_audioState.dspSettings.ReverbLevel);

            XAUDIO2_FILTER_PARAMETERS FilterParametersDirect = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI/6.0f * g_audioState.dspSettings.LPFDirectCoefficient), 1.0f }; // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here
            voice->SetOutputFilterParameters(g_audioState.pMasteringVoice, &FilterParametersDirect);
            XAUDIO2_FILTER_PARAMETERS FilterParametersReverb = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI/6.0f * g_audioState.dspSettings.LPFReverbCoefficient), 1.0f }; // see XAudio2CutoffFrequencyToRadians() in XAudio2.h for more information on the formula used here
            voice->SetOutputFilterParameters(g_audioState.pSubmixVoice, &FilterParametersReverb);
        }
    }

    g_audioState.nFrameToApply3DAudio++;
    g_audioState.nFrameToApply3DAudio &= 1;

    return S_OK;
}
void Sound::playSoundEffect(SoundEffect effect, X3DAUDIO_EMITTER* emit)
{
	IXAudio2SourceVoice* voice = getSFXVoice();

	voice->FlushSourceBuffers();
	
	switch (effect) {
	case SFX_LASER:
		{
			voice->SubmitSourceBuffer(laserBufferDetails, laserWMABuffer);
			break;
		}
	case SFX_CRASH:
		{
			voice->SubmitSourceBuffer(crashBufferDetails, crashWMABuffer);
			break;
		}
	case SFX_BOOST:
		{
			voice->SubmitSourceBuffer(boostBufferDetails, boostWMABuffer);
			break;
		}
	case SFX_DROPMINE:
		{
			voice->SubmitSourceBuffer(dropmineBufferDetails, dropmineWMABuffer);
			break;
		}
	case SFX_SCREAM:
		{
			// Now pick one of the three screams randomly
			int choice = std::rand() % 3;


			voice->SetVolume(2.0f);
			switch (choice) {
				case 0:	voice->SubmitSourceBuffer(scream1BufferDetails, scream1WMABuffer);
					break;
				case 1:	voice->SubmitSourceBuffer(scream2BufferDetails, scream2WMABuffer);
					break;
				case 2:	voice->SubmitSourceBuffer(scream3BufferDetails, scream3WMABuffer);
					break;
				default:
					voice->SubmitSourceBuffer(scream1BufferDetails, scream1WMABuffer);
			}

			break;
		}
	case SFX_CAREXPLODE:
		{
			voice->SetVolume(2.0f);
			voice->SubmitSourceBuffer(carexplodeBufferDetails, carexplodeWMABuffer);
			break;
		}
	case SFX_EXPLOSION:
		{
			voice->SubmitSourceBuffer(explosionBufferDetails, explosionWMABuffer);
			break;
		}
	case SFX_BEEP:
		{
			voice->SubmitSourceBuffer(beepBufferDetails, beepWMABuffer);
			break;
		}
	case SFX_ROCKETLAUNCH:
		{
			voice->SubmitSourceBuffer(rocketlaunchBufferDetails, rocketlaunchWMABuffer);
			break;
		}
	case SFX_PICKUP:
		{
			voice->SetVolume(2.0f);
			voice->SubmitSourceBuffer(pickupBufferDetails, pickupWMABuffer);
			break;
		}
	case SFX_SELECT:
		{
			voice->SubmitSourceBuffer(selectBufferDetails, selectWMABuffer);
			break;
		}
	case SFX_SHOTGUN:
		{
			voice->SetVolume(2.5f);
			voice->SubmitSourceBuffer(shotgunBufferDetails, shotgunWMABuffer);
			break;
		}
	case SFX_TAKENLEAD:
		{
			voice->SubmitSourceBuffer(takenleadBufferDetails, takenleadWMABuffer);
			break;
		}
	case SFX_LOSTLEAD:
		{
			voice->SubmitSourceBuffer(lostleadBufferDetails, lostleadWMABuffer);
			break;
		}
	case SFX_NOAMMO:
		{
			voice->SubmitSourceBuffer(noammoBufferDetails, noammoWMABuffer);
			break;
		}
	case SFX_ONE:
		{
			voice->SubmitSourceBuffer(oneBufferDetails, oneWMABuffer);
			break;
		}
	case SFX_TWO:
		{
			voice->SubmitSourceBuffer(twoBufferDetails, twoWMABuffer);
			break;
		}
	case SFX_THREE:
		{
			voice->SubmitSourceBuffer(threeBufferDetails, threeWMABuffer);
			break;
		}
	default:
		break;
	}




	X3DAudioCalculate(audio3DHandle, &listener, emit,
		X3DAUDIO_CALCULATE_MATRIX | X3DAUDIO_CALCULATE_DOPPLER | X3DAUDIO_CALCULATE_LPF_DIRECT,
		&dspSettings);
	
	voice->SetOutputMatrix(smSFX, 1, details.OutputFormat.Format.nChannels, dspSettings.pMatrixCoefficients);
	voice->SetFrequencyRatio(dspSettings.DopplerFactor);

	XAUDIO2_FILTER_PARAMETERS filterParameters = { LowPassFilter, 2.0f * sinf(X3DAUDIO_PI/6.0f * dspSettings.LPFDirectCoefficient), 1.0f };
	voice->SetFilterParameters(&filterParameters);
	
	voice->Start();
}
예제 #6
0
void WaveBank::Impl::Play( int index, float volume, float pitch, float pan )
{
    assert( volume >= -XAUDIO2_MAX_VOLUME_LEVEL && volume <= XAUDIO2_MAX_VOLUME_LEVEL );
    assert( pitch >= -1.f && pitch <= 1.f );
    assert( pan >= -1.f && pan <= 1.f );

    if ( mStreaming )
    {
        DebugTrace( "ERROR: One-shots can only be created from an in-memory wave bank\n");
        throw std::exception( "WaveBank::Play" );
    }

    if ( index < 0 || uint32_t(index) >= mReader.Count() )
    {
        DebugTrace( "WARNING: Index %d not found in wave bank with only %u entries, one-shot not triggered\n", index, mReader.Count() );
        return;
    }

    if ( !mPrepared )
    {
        mReader.WaitOnPrepare();
        mPrepared = true;
    }

    char wfxbuff[64];
    auto wfx = reinterpret_cast<WAVEFORMATEX*>( wfxbuff );
    HRESULT hr = mReader.GetFormat( index, wfx, 64 );
    ThrowIfFailed( hr );

    IXAudio2SourceVoice* voice = nullptr;
    mEngine->AllocateVoice( wfx, SoundEffectInstance_Default, true, &voice );

    if ( !voice )
        return;

    if ( volume != 1.f )
    {
        hr = voice->SetVolume( volume );
        ThrowIfFailed( hr );
    }

    if ( pitch != 0.f )
    {
        float fr = XAudio2SemitonesToFrequencyRatio( pitch * 12.f );

        hr = voice->SetFrequencyRatio( fr );
        ThrowIfFailed( hr );
    }

    if ( pan != 0.f )
    {
        float matrix[16];
        if ( ComputePan( pan, wfx->nChannels, matrix ) )
        {
            hr = voice->SetOutputMatrix( nullptr, wfx->nChannels, mEngine->GetOutputChannels(), matrix );
            ThrowIfFailed( hr );
        }
    }

    hr = voice->Start( 0 );
    ThrowIfFailed( hr );

    XAUDIO2_BUFFER buffer;
    memset( &buffer, 0, sizeof(buffer) );

    hr = mReader.GetWaveData( index, &buffer.pAudioData, buffer.AudioBytes );
    ThrowIfFailed( hr );

    WaveBankReader::Metadata metadata;
    hr = mReader.GetMetadata( index, metadata );
    ThrowIfFailed( hr );

    buffer.Flags = XAUDIO2_END_OF_STREAM;
    buffer.pContext = this;

#if defined(_XBOX_ONE) || (_WIN32_WINNT < _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN10)

    XAUDIO2_BUFFER_WMA wmaBuffer;
    memset( &wmaBuffer, 0, sizeof(wmaBuffer) );

    uint32_t tag;
    hr = mReader.GetSeekTable( index, &wmaBuffer.pDecodedPacketCumulativeBytes, wmaBuffer.PacketCount, tag );
    ThrowIfFailed( hr );

    if ( tag == WAVE_FORMAT_WMAUDIO2 || tag == WAVE_FORMAT_WMAUDIO3 )
    {
        hr = voice->SubmitSourceBuffer( &buffer, &wmaBuffer );
    }
    else
#endif
    {
        hr = voice->SubmitSourceBuffer( &buffer, nullptr );
    }
    if ( FAILED(hr) )
    {
        DebugTrace( "ERROR: WaveBank failed (%08X) when submitting buffer:\n", hr );
        DebugTrace( "\tFormat Tag %u, %u channels, %u-bit, %u Hz, %u bytes\n", wfx->wFormatTag, 
                    wfx->nChannels, wfx->wBitsPerSample, wfx->nSamplesPerSec, metadata.lengthBytes );
        throw std::exception( "SubmitSourceBuffer" );
    }

    InterlockedIncrement( &mOneShots );
}