/**
 * Initializes a source with a given wave instance and prepares it for playback.
 *
 * @param	WaveInstance	wave instance being primed for playback
 * @return	true			if initialization was successful, false otherwise
 */
bool FCoreAudioSoundSource::Init( FWaveInstance* InWaveInstance )
{
	if (InWaveInstance->OutputTarget != EAudioOutputTarget::Controller)
	{
		// Find matching buffer.
		Buffer = FCoreAudioSoundBuffer::Init( AudioDevice, InWaveInstance->WaveData, InWaveInstance->StartTime > 0.f );
	
		// Buffer failed to be created, or there was an error with the compressed data
		if( Buffer && Buffer->NumChannels > 0 )
		{
			SCOPE_CYCLE_COUNTER( STAT_AudioSourceInitTime );
		
			WaveInstance = InWaveInstance;

			// Set whether to apply reverb
			SetReverbApplied( true );

			if (WaveInstance->StartTime > 0.f)
			{
				Buffer->Seek(WaveInstance->StartTime);
			}

			// Submit audio buffers
			switch( Buffer->SoundFormat )
			{
				case SoundFormat_PCM:
				case SoundFormat_PCMPreview:
					SubmitPCMBuffers();
					break;
				
				case SoundFormat_PCMRT:
					SubmitPCMRTBuffers();
					break;
			}

			// Initialization succeeded.
			return( true );
		}
	}
	
	// Initialization failed.
	return false;
}
	bool FMixerSource::Init(FWaveInstance* InWaveInstance)
	{
		AUDIO_MIXER_CHECK(MixerBuffer);
		AUDIO_MIXER_CHECK(MixerBuffer->IsRealTimeSourceReady());

		// Get the number of frames before creating the buffer
		int32 NumFrames = INDEX_NONE;

		if (InWaveInstance->WaveData->DecompressionType != EDecompressionType::DTYPE_Procedural)
		{
			const int32 NumBytes = InWaveInstance->WaveData->RawPCMDataSize;
			NumFrames = NumBytes / (InWaveInstance->WaveData->NumChannels * sizeof(int16));
		}

		FSoundBuffer* SoundBuffer = static_cast<FSoundBuffer*>(MixerBuffer);
		if (SoundBuffer->NumChannels > 0)
		{
			SCOPE_CYCLE_COUNTER(STAT_AudioSourceInitTime);

			AUDIO_MIXER_CHECK(MixerDevice);
			MixerSourceVoice = MixerDevice->GetMixerSourceVoice(InWaveInstance, this, UseHRTSpatialization());
			if (!MixerSourceVoice)
			{
				return false;
			}

			// Default the submix to use to use the master submix
			FMixerSubmix* SourceSubmix = MixerDevice->GetMasterSubmix();

			// If we're told to use a different submix, then grab that submix and set it for the sound
			if (InWaveInstance->SoundSubmix)
			{
				FMixerSubmix** Submix = MixerDevice->GetSubmix(InWaveInstance->SoundSubmix);
				check(Submix);
				SourceSubmix = *Submix;
			}

			// Initialize the source voice with the necessary format information
			FMixerSourceVoiceInitParams InitParams;
			InitParams.BufferQueueListener = this;
			InitParams.NumInputChannels = InWaveInstance->WaveData->NumChannels;
			InitParams.NumInputFrames = NumFrames;
			InitParams.OwningSubmix = SourceSubmix;
			InitParams.SourceVoice = MixerSourceVoice;
			InitParams.bUseHRTFSpatialization = UseHRTSpatialization();

			// Check to see if this sound has been flagged to be in debug mode
#if AUDIO_MIXER_ENABLE_DEBUG_MODE
			InitParams.DebugName = InWaveInstance->GetName();

			bool bIsDebug = false;
			FString WaveInstanceName = WaveInstance->GetName();
			FString TestName = GEngine->GetAudioDeviceManager()->GetAudioMixerDebugSoundName();
			if (WaveInstanceName.Contains(TestName))
			{
				bDebugMode = true;
				InitParams.bIsDebugMode = bDebugMode;
			}
#endif

			if (MixerSourceVoice->Init(InitParams))
			{
				AUDIO_MIXER_CHECK(WaveInstance);
				if (WaveInstance->StartTime)
				{
					MixerBuffer->Seek(WaveInstance->StartTime);
				}

				const EBufferType::Type BufferType = MixerBuffer->GetType();
				switch (BufferType)
				{
					case EBufferType::PCM:
					case EBufferType::PCMPreview:
						SubmitPCMBuffers();
						break;

					case EBufferType::PCMRealTime:
					case EBufferType::Streaming:
						SubmitPCMRTBuffers();
						break;

					case EBufferType::Invalid:
						break;
				}

				bInitialized = true;

				ChannelMap.Reset();

				Update();

				return true;
			}
		}
		return false;
	}