本文整理汇总了C++中FAudioDeviceManager类的典型用法代码示例。如果您正苦于以下问题:C++ FAudioDeviceManager类的具体用法?C++ FAudioDeviceManager怎么用?C++ FAudioDeviceManager使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了FAudioDeviceManager类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1:
/**
* Static function used to create an OpenAL buffer and upload raw PCM data to.
*
* @param InWave USoundWave to use as template and wave source
* @param AudioDevice audio device to attach created buffer to
* @return FXAudio2SoundBuffer pointer if buffer creation succeeded, NULL otherwise
*/
FXAudio2SoundBuffer* FXAudio2SoundBuffer::CreatePreviewBuffer( FXAudio2Device* XAudio2Device, USoundWave* Wave, FXAudio2SoundBuffer* Buffer )
{
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
check(AudioDeviceManager != nullptr);
if (Buffer)
{
AudioDeviceManager->FreeBufferResource(Buffer);
}
// Create new buffer.
Buffer = new FXAudio2SoundBuffer( XAudio2Device, SoundFormat_PCMPreview );
// Take ownership the PCM data
Buffer->PCM.PCMData = Wave->RawPCMData;
Buffer->PCM.PCMDataSize = Wave->RawPCMDataSize;
Wave->RawPCMData = NULL;
// Copy over whether this data should be freed on delete
Buffer->bDynamicResource = Wave->bDynamicResource;
Buffer->InitWaveFormatEx( WAVE_FORMAT_PCM, Wave, true );
AudioDeviceManager->TrackResource(Wave, Buffer);
return( Buffer );
}
示例2: FXAudio2SoundBuffer
/**
* Static function used to create an OpenAL buffer and upload decompressed ogg vorbis data to.
*
* @param InWave USoundWave to use as template and wave source
* @param AudioDevice audio device to attach created buffer to
* @return FXAudio2SoundBuffer pointer if buffer creation succeeded, NULL otherwise
*/
FXAudio2SoundBuffer* FXAudio2SoundBuffer::CreateNativeBuffer( FXAudio2Device* XAudio2Device, USoundWave* Wave )
{
// Check to see if thread has finished decompressing on the other thread
if( Wave->AudioDecompressor != NULL )
{
Wave->AudioDecompressor->EnsureCompletion();
// Remove the decompressor
delete Wave->AudioDecompressor;
Wave->AudioDecompressor = NULL;
}
// Create new buffer.
FXAudio2SoundBuffer* Buffer = new FXAudio2SoundBuffer( XAudio2Device, SoundFormat_PCM );
// Take ownership the PCM data
Buffer->PCM.PCMData = Wave->RawPCMData;
Buffer->PCM.PCMDataSize = Wave->RawPCMDataSize;
Wave->RawPCMData = NULL;
// Keep track of associated resource name.
Buffer->InitWaveFormatEx( WAVE_FORMAT_PCM, Wave, true );
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
check(AudioDeviceManager != nullptr);
AudioDeviceManager->TrackResource(Wave, Buffer);
Wave->RemoveAudioResource();
return( Buffer );
}
示例3: CreatePreviewBuffer
/**
* Static function used to create an OpenAL buffer and upload raw PCM data to.
*
* @param InWave USoundWave to use as template and wave source
* @param AudioDevice audio device to attach created buffer to
* @return FCoreAudioSoundBuffer pointer if buffer creation succeeded, NULL otherwise
*/
FCoreAudioSoundBuffer* FCoreAudioSoundBuffer::CreatePreviewBuffer( FCoreAudioDevice* CoreAudioDevice, USoundWave* Wave, FCoreAudioSoundBuffer* Buffer )
{
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
check(AudioDeviceManager != nullptr);
if (Buffer)
{
AudioDeviceManager->FreeBufferResource( Buffer );
}
// Create new buffer.
Buffer = new FCoreAudioSoundBuffer( CoreAudioDevice, SoundFormat_PCMPreview );
// Take ownership the PCM data
Buffer->PCMData = Wave->RawPCMData;
Buffer->PCMDataSize = Wave->RawPCMDataSize;
Wave->RawPCMData = NULL;
// Copy over whether this data should be freed on delete
Buffer->bDynamicResource = Wave->bDynamicResource;
Buffer->InitAudioStreamBasicDescription( kAudioFormatLinearPCM, Wave, true );
AudioDeviceManager->TrackResource( Wave, Buffer );
return( Buffer );
}
示例4: if
void USoundClass::PostLoad()
{
Super::PostLoad();
for (int32 ChildIndex = ChildClasses.Num()-1; ChildIndex >= 0; ChildIndex--)
{
if (ChildClasses[ChildIndex] != NULL && ChildClasses[ChildIndex]->GetLinkerUE4Version() < VER_UE4_SOUND_CLASS_GRAPH_EDITOR)
{
// first come, first served
if (ChildClasses[ChildIndex]->ParentClass == nullptr)
{
ChildClasses[ChildIndex]->ParentClass = this;
}
// if already set, we can't be a parent of this child
else if (ChildClasses[ChildIndex]->ParentClass != this)
{
UE_LOG(LogAudio, Warning, TEXT("SoundClass '%s' - '%s' removed from children as '%s' is its parent."), *GetName(), *ChildClasses[ChildIndex]->GetName(), *ChildClasses[ChildIndex]->ParentClass->GetName());
ChildClasses.RemoveAt(ChildIndex);
}
}
}
// Use the main/default audio device for storing and retrieving sound class properties
FAudioDeviceManager* AudioDeviceManager = (GEngine ? GEngine->GetAudioDeviceManager() : nullptr);
// Force the properties to be initialized for this SoundClass on all active audio devices
if (AudioDeviceManager)
{
AudioDeviceManager->RegisterSoundClass(this);
}
}
示例5: switch
FIOSAudioSoundBuffer* FIOSAudioSoundBuffer::CreateNativeBuffer(FIOSAudioDevice* IOSAudioDevice, USoundWave* InWave)
{
FWaveModInfo WaveInfo;
InWave->InitAudioResource(IOSAudioDevice->GetRuntimeFormat(InWave));
if (!InWave->ResourceData || InWave->ResourceSize <= 0 || !WaveInfo.ReadWaveInfo(InWave->ResourceData, InWave->ResourceSize))
{
InWave->RemoveAudioResource();
return NULL;
}
uint32 UncompressedBlockSize = 0;
uint32 CompressedBlockSize = 0;
const uint32 PreambleSize = 7;
const uint32 BlockSize = *WaveInfo.pBlockAlign;
switch (*WaveInfo.pFormatTag)
{
case SoundFormat_ADPCM:
// (BlockSize - PreambleSize) * 2 (samples per byte) + 2 (preamble samples)
UncompressedBlockSize = (2 + (BlockSize - PreambleSize) * 2) * sizeof(int16);
CompressedBlockSize = BlockSize;
if ((WaveInfo.SampleDataSize % CompressedBlockSize) != 0)
{
InWave->RemoveAudioResource();
return NULL;
}
break;
case SoundFormat_LPCM:
break;
}
// Create new buffer
FIOSAudioSoundBuffer* Buffer = new FIOSAudioSoundBuffer(IOSAudioDevice, static_cast<ESoundFormat>(*WaveInfo.pFormatTag));
Buffer->NumChannels = InWave->NumChannels;
Buffer->SampleRate = InWave->SampleRate;
Buffer->UncompressedBlockSize = UncompressedBlockSize;
Buffer->CompressedBlockSize = CompressedBlockSize;
Buffer->BufferSize = WaveInfo.SampleDataSize;
Buffer->SampleData = static_cast<int16*>(FMemory::Malloc(Buffer->BufferSize));
FMemory::Memcpy(Buffer->SampleData, WaveInfo.SampleDataStart, Buffer->BufferSize);
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
check(AudioDeviceManager != nullptr);
AudioDeviceManager->TrackResource(InWave, Buffer);
InWave->RemoveAudioResource();
return Buffer;
}
示例6: check
void USoundWave::FreeResources()
{
check(IsInAudioThread());
// Housekeeping of stats
DEC_FLOAT_STAT_BY( STAT_AudioBufferTime, Duration );
DEC_FLOAT_STAT_BY( STAT_AudioBufferTimeChannels, NumChannels * Duration );
// GEngine is NULL during script compilation and GEngine->Client and its audio device might be
// destroyed first during the exit purge.
if( GEngine && !GExitPurge )
{
// Notify the audio device to free the bulk data associated with this wave.
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
if (AudioDeviceManager)
{
AudioDeviceManager->StopSoundsUsingResource(this);
AudioDeviceManager->FreeResource(this);
}
}
if (CachedRealtimeFirstBuffer)
{
FMemory::Free(CachedRealtimeFirstBuffer);
CachedRealtimeFirstBuffer = nullptr;
}
// Just in case the data was created but never uploaded
if (RawPCMData)
{
FMemory::Free(RawPCMData);
RawPCMData = nullptr;
}
// Remove the compressed copy of the data
RemoveAudioResource();
// Stat housekeeping
DEC_DWORD_STAT_BY(STAT_AudioMemorySize, TrackedMemoryUsage);
DEC_DWORD_STAT_BY(STAT_AudioMemory, TrackedMemoryUsage);
TrackedMemoryUsage = 0;
ResourceID = 0;
bDynamicResource = false;
DecompressionType = DTYPE_Setup;
bDecompressedFromOgg = 0;
USoundWave* SoundWave = this;
FAudioThread::RunCommandOnGameThread([SoundWave]()
{
SoundWave->ResourceState = ESoundWaveResourceState::Freed;
}, TStatId());
}
示例7: BeginDestroy
void USoundMix::BeginDestroy()
{
if (!GExitPurge && GEngine)
{
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
if (AudioDeviceManager)
{
AudioDeviceManager->RemoveSoundMix(this);
}
}
Super::BeginDestroy();
}
示例8: SetDebugSoloSoundCue
void FAudioDeviceManager::SetDebugSoloSoundCue(const TCHAR* SoundCue)
{
if (!IsInAudioThread())
{
FAudioDeviceManager* AudioDeviceManager = this;
FAudioThread::RunCommandOnAudioThread([AudioDeviceManager, SoundCue]()
{
AudioDeviceManager->SetDebugSoloSoundCue(SoundCue);
});
return;
}
DebugNames.DebugSoloSoundCue = SoundCue;
}
示例9:
void FAudioDeviceManager::ToggleVisualize3dDebug()
{
if (!IsInAudioThread())
{
FAudioDeviceManager* AudioDeviceManager = this;
FAudioThread::RunCommandOnAudioThread([AudioDeviceManager]()
{
AudioDeviceManager->ToggleVisualize3dDebug();
});
return;
}
bVisualize3dDebug = !bVisualize3dDebug;
}
示例10: TogglePlayAllDeviceAudio
void FAudioDeviceManager::TogglePlayAllDeviceAudio()
{
if (!IsInAudioThread())
{
FAudioDeviceManager* AudioDeviceManager = this;
FAudioThread::RunCommandOnAudioThread([AudioDeviceManager]()
{
AudioDeviceManager->TogglePlayAllDeviceAudio();
});
return;
}
bPlayAllDeviceAudio = !bPlayAllDeviceAudio;
}
示例11: DrawDebugInfo
void FSoundSource::DrawDebugInfo()
{
// Draw 3d Debug information about this source, if enabled
FAudioDeviceManager* DeviceManager = GEngine->GetAudioDeviceManager();
if (DeviceManager && DeviceManager->IsVisualizeDebug3dEnabled())
{
const uint32 AudioComponentID = WaveInstance->ActiveSound->GetAudioComponentID();
if (AudioComponentID > 0)
{
DECLARE_CYCLE_STAT(TEXT("FAudioThreadTask.DrawSourceDebugInfo"), STAT_AudioDrawSourceDebugInfo, STATGROUP_TaskGraphTasks);
USoundBase* Sound = WaveInstance->ActiveSound->GetSound();
const FVector Location = WaveInstance->Location;
const bool bSpatialized = Buffer->NumChannels == 2 && WaveInstance->bUseSpatialization;
const FVector LeftChannelSourceLoc = LeftChannelSourceLocation;
const FVector RightChannelSourceLoc = RightChannelSourceLocation;
FAudioThread::RunCommandOnGameThread([AudioComponentID, Sound, bSpatialized, Location, LeftChannelSourceLoc, RightChannelSourceLoc]()
{
UAudioComponent* AudioComponent = UAudioComponent::GetAudioComponentFromID(AudioComponentID);
if (AudioComponent)
{
UWorld* SoundWorld = AudioComponent->GetWorld();
if (SoundWorld)
{
FRotator SoundRotation = AudioComponent->GetComponentRotation();
DrawDebugCrosshairs(SoundWorld, Location, SoundRotation, 20.0f, FColor::White, false, -1.0f, SDPG_Foreground);
if (bSpatialized)
{
DrawDebugCrosshairs(SoundWorld, LeftChannelSourceLoc, SoundRotation, 20.0f, FColor::Red, false, -1.0f, SDPG_Foreground);
DrawDebugCrosshairs(SoundWorld, RightChannelSourceLoc, SoundRotation, 20.0f, FColor::Green, false, -1.0f, SDPG_Foreground);
}
const FString Name = Sound->GetName();
DrawDebugString(SoundWorld, AudioComponent->GetComponentLocation() + FVector(0, 0, 32), *Name, nullptr, FColor::White, 0.033, false);
}
}
}, GET_STATID(STAT_AudioDrawSourceDebugInfo));
}
}
}
示例12: DECLARE_CYCLE_STAT
void FAudioDeviceManager::RemoveSoundMix(USoundMix* SoundMix)
{
if (!IsInAudioThread())
{
DECLARE_CYCLE_STAT(TEXT("FAudioThreadTask.RemoveSoundMix"), STAT_AudioRemoveSoundMix, STATGROUP_AudioThreadCommands);
FAudioDeviceManager* AudioDeviceManager = this;
FAudioThread::RunCommandOnAudioThread([AudioDeviceManager, SoundMix]()
{
AudioDeviceManager->RemoveSoundMix(SoundMix);
}, GET_STATID(STAT_AudioRemoveSoundMix));
return;
}
for (FAudioDevice* AudioDevice : Devices)
{
if (AudioDevice)
{
AudioDevice->RemoveSoundMix(SoundMix);
}
}
}
示例13: return
/**
* Static function used to create a buffer.
*
* @param InWave USoundWave to use as template and wave source
* @param AudioDevice audio device to attach created buffer to
* @return FXAudio2SoundBuffer pointer if buffer creation succeeded, NULL otherwise
*/
FXAudio2SoundBuffer* FXAudio2SoundBuffer::Init( FAudioDevice* AudioDevice, USoundWave* Wave, bool bForceRealTime )
{
// Can't create a buffer without any source data
if( Wave == NULL || Wave->NumChannels == 0 )
{
return( NULL );
}
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
FXAudio2Device* XAudio2Device = ( FXAudio2Device* )AudioDevice;
FXAudio2SoundBuffer* Buffer = NULL;
// Allow the precache to happen if necessary
EDecompressionType DecompressionType = Wave->DecompressionType;
if (bForceRealTime && DecompressionType != DTYPE_Setup && DecompressionType != DTYPE_Streaming)
{
DecompressionType = DTYPE_RealTime;
}
switch( DecompressionType )
{
case DTYPE_Setup:
// Has circumvented precache mechanism - precache now
AudioDevice->Precache(Wave, true, false);
// if it didn't change, we will recurse forever
check(Wave->DecompressionType != DTYPE_Setup);
// Recall this function with new decompression type
return( Init( AudioDevice, Wave, bForceRealTime ) );
case DTYPE_Preview:
// Find the existing buffer if any
if( Wave->ResourceID )
{
Buffer = (FXAudio2SoundBuffer*)AudioDeviceManager->GetSoundBufferForResourceID(Wave->ResourceID);
}
// Override with any new PCM data even if some already exists.
if( Wave->RawPCMData )
{
// Upload the preview PCM data to it
Buffer = CreatePreviewBuffer( XAudio2Device, Wave, Buffer );
}
break;
case DTYPE_Procedural:
// Always create a new buffer for streaming procedural data
Buffer = CreateProceduralBuffer( XAudio2Device, Wave );
break;
case DTYPE_RealTime:
// Always create a new buffer for streaming ogg vorbis data
Buffer = CreateQueuedBuffer( XAudio2Device, Wave );
break;
case DTYPE_Native:
case DTYPE_Xenon:
// Upload entire wav to XAudio2
if( Wave->ResourceID )
{
Buffer = (FXAudio2SoundBuffer*)AudioDeviceManager->GetSoundBufferForResourceID(Wave->ResourceID);
}
if( Buffer == NULL )
{
Buffer = CreateNativeBuffer( XAudio2Device, Wave );
}
break;
case DTYPE_Streaming:
// Always create a new buffer for streaming sounds
Buffer = CreateStreamingBuffer( XAudio2Device, Wave );
break;
case DTYPE_Invalid:
default:
// Invalid will be set if the wave cannot be played
break;
}
return( Buffer );
}
示例14: TEXT
UObject* UMP3SoundFactory::FactoryCreateBinary(UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn)
{
FEditorDelegates::OnAssetPreImport.Broadcast(this, Class, InParent, Name, Type);
if (mpg123_init == nullptr)
{
Warn->Logf(ELogVerbosity::Error, TEXT("Function pointer was null. Was %s found?"), DLL_NAME);
FEditorDelegates::OnAssetPostImport.Broadcast(this, nullptr);
return nullptr;
}
// if the sound already exists, remember the user settings
USoundWave* ExistingSound = FindObject<USoundWave>(InParent, *Name.ToString());
// stop playing the file, if it already exists (e.g. reimport)
TArray<UAudioComponent*> ComponentsToRestart;
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
if (AudioDeviceManager && ExistingSound)
{
AudioDeviceManager->StopSoundsUsingResource(ExistingSound, ComponentsToRestart);
}
// Read the mp3 header and make sure we have valid data
UMP3Decoder Decoder(Warn);
Decoder.Init(Buffer, BufferEnd);
if (Decoder.BitsPerSample != 16)
{
Warn->Logf(ELogVerbosity::Error, TEXT("Unreal only supports 16bit WAVE data (%s)."), *Name.ToString());
FEditorDelegates::OnAssetPostImport.Broadcast(this, nullptr);
return nullptr;
}
if (Decoder.Channels != 1 && Decoder.Channels != 2)
{
Warn->Logf(ELogVerbosity::Error, TEXT("Unreal only supports 1-2 channel WAVE data (Mono/Stereo). (%s)."), *Name.ToString());
FEditorDelegates::OnAssetPostImport.Broadcast(this, nullptr);
return nullptr;
}
//on reimport, reuse settings, wipe data. otherwise create new. (UE4 WAVE import has some more checks, maybe implement, too?)
USoundWave* Sound;
if (ExistingSound && bMP3SoundFactoryIsReimport)
{
Sound = ExistingSound;
Sound->FreeResources();
Sound->InvalidateCompressedData();
}
else
{
Sound = NewObject<USoundWave>(InParent, Name, Flags);
}
Sound->AssetImportData->Update(GetCurrentFilename());
TArray<uint8> RawWavBuffer;
RawWavBuffer.Reserve((BufferEnd - Buffer) * 16);
//actual decoding
Decoder.Decode(RawWavBuffer);
Sound->RawData.Lock(LOCK_READ_WRITE);
void* LockedData = Sound->RawData.Realloc(RawWavBuffer.Num() * RawWavBuffer.GetTypeSize());
FMemory::Memcpy(LockedData, RawWavBuffer.GetData(), RawWavBuffer.Num() * RawWavBuffer.GetTypeSize());
Sound->RawData.Unlock();
RawWavBuffer.Empty();
// Calculate duration.
Sound->Duration = (float)Decoder.SizeInBytes / Decoder.Samplerate / Decoder.Channels / (BITS_PER_SAMPLE / 8);
Sound->SampleRate = Decoder.Samplerate;
Sound->NumChannels = Decoder.Channels;
Sound->RawPCMDataSize = Decoder.SizeInBytes;
FEditorDelegates::OnAssetPostImport.Broadcast(this, Sound);
if (ExistingSound)
{
Sound->PostEditChange();
}
for (int32 ComponentIndex = 0; ComponentIndex < ComponentsToRestart.Num(); ++ComponentIndex)
{
ComponentsToRestart[ComponentIndex]->Play();
}
return Sound;
}
示例15: SCOPE_CYCLE_COUNTER
FALSoundBuffer* FALSoundBuffer::CreateNativeBuffer( FALAudioDevice* AudioDevice, USoundWave* Wave)
{
SCOPE_CYCLE_COUNTER( STAT_AudioResourceCreationTime );
// This code is not relevant for now on HTML5 but adding this for consistency with other platforms.
// Check to see if thread has finished decompressing on the other thread
if (Wave->AudioDecompressor != NULL)
{
Wave->AudioDecompressor->EnsureCompletion();
// Remove the decompressor
delete Wave->AudioDecompressor;
Wave->AudioDecompressor = NULL;
}
// Can't create a buffer without any source data
if( Wave == NULL || Wave->NumChannels == 0 )
{
return( NULL );
}
Wave->InitAudioResource(AudioDevice->GetRuntimeFormat(Wave));
FALSoundBuffer* Buffer = NULL;
FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager();
check(AudioDeviceManager != nullptr);
// Find the existing buffer if any
if( Wave->ResourceID )
{
Buffer = static_cast<FALSoundBuffer*>(AudioDeviceManager->WaveBufferMap.FindRef(Wave->ResourceID));
}
if( Buffer == NULL )
{
// Create new buffer.
Buffer = new FALSoundBuffer( AudioDevice );
alGenBuffers( 1, Buffer->BufferIds );
AudioDevice->alError( TEXT( "RegisterSound" ) );
AudioDeviceManager->TrackResource(Wave, Buffer);
Buffer->InternalFormat = AudioDevice->GetInternalFormat( Wave->NumChannels );
Buffer->NumChannels = Wave->NumChannels;
Buffer->SampleRate = Wave->SampleRate;
if (Wave->RawPCMData)
{
// upload it
Buffer->BufferSize = Wave->RawPCMDataSize;
alBufferData( Buffer->BufferIds[0], Buffer->InternalFormat, Wave->RawPCMData, Wave->RawPCMDataSize, Buffer->SampleRate );
// Free up the data if necessary
if( Wave->bDynamicResource )
{
FMemory::Free( Wave->RawPCMData );
Wave->RawPCMData = NULL;
Wave->bDynamicResource = false;
}
}
else
{
// get the raw data
uint8* SoundData = ( uint8* )Wave->RawData.Lock( LOCK_READ_ONLY );
// it's (possibly) a pointer to a wave file, so skip over the header
int SoundDataSize = Wave->RawData.GetBulkDataSize();
// is there a wave header?
FWaveModInfo WaveInfo;
if (WaveInfo.ReadWaveInfo(SoundData, SoundDataSize))
{
// if so, modify the location and size of the sound data based on header
SoundData = WaveInfo.SampleDataStart;
SoundDataSize = WaveInfo.SampleDataSize;
}
// let the Buffer know the final size
Buffer->BufferSize = SoundDataSize;
// upload it
alBufferData( Buffer->BufferIds[0], Buffer->InternalFormat, SoundData, Buffer->BufferSize, Buffer->SampleRate );
// unload it
Wave->RawData.Unlock();
}
if( AudioDevice->alError( TEXT( "RegisterSound (buffer data)" ) ) || ( Buffer->BufferSize == 0 ) )
{
Buffer->InternalFormat = 0;
}
if( Buffer->InternalFormat == 0 )
{
UE_LOG ( LogAudio, Log,TEXT( "Audio: sound format not supported for '%s' (%d)" ), *Wave->GetName(), Wave->NumChannels );
delete Buffer;
Buffer = NULL;
}
}
//.........这里部分代码省略.........