void USoundMod::Parse(class FAudioDevice* AudioDevice, const UPTRINT NodeWaveInstanceHash, FActiveSound& ActiveSound, const FSoundParseParameters& ParseParams, TArray<FWaveInstance*>& WaveInstances) { FWaveInstance* WaveInstance = ActiveSound.FindWaveInstance(NodeWaveInstanceHash); // Create a new WaveInstance if this SoundWave doesn't already have one associated with it. if (WaveInstance == NULL) { const int32 SampleRate = 44100; // Create a new wave instance and associate with the ActiveSound WaveInstance = new FWaveInstance(&ActiveSound); WaveInstance->WaveInstanceHash = NodeWaveInstanceHash; ActiveSound.WaveInstances.Add(NodeWaveInstanceHash, WaveInstance); // Create streaming wave object USoundModWave* ModWave = NewObject<USoundModWave>(); ModWave->SampleRate = SampleRate; ModWave->NumChannels = 2; ModWave->Duration = INDEFINITELY_LOOPING_DURATION; ModWave->bLooping = bLooping; if (ResourceData == NULL) { RawData.GetCopy((void**)&ResourceData, true); } ModWave->xmpContext = xmp_create_context(); xmp_load_module_from_memory(ModWave->xmpContext, ResourceData, RawData.GetBulkDataSize()); xmp_start_player(ModWave->xmpContext, SampleRate, 0); WaveInstance->WaveData = ModWave; } WaveInstance->WaveData->Parse(AudioDevice, NodeWaveInstanceHash, ActiveSound, ParseParams, WaveInstances); }
static qboolean S_XMP_CodecOpenStream (snd_stream_t *stream) { /* need to load the whole file into memory and pass it to libxmp * using xmp_load_module_from_memory() which requires libxmp >= 4.2. * libxmp-4.0/4.1 only have xmp_load_module() which accepts a file * name which isn't good with files in containers like paks, etc. */ xmp_context c; byte *moddata; long len; int mark; c = xmp_create_context(); if (c == NULL) return false; len = FS_filelength (&stream->fh); mark = Hunk_LowMark(); moddata = (byte *) Hunk_Alloc(len); FS_fread(moddata, 1, len, &stream->fh); if (xmp_load_module_from_memory(c, moddata, len) != 0) { Con_DPrintf("Could not load module %s\n", stream->name); goto err1; } Hunk_FreeToLowMark(mark); /* free original file data */ stream->priv = c; if (shm->speed > XMP_MAX_SRATE) stream->info.rate = 44100; else if (shm->speed < XMP_MIN_SRATE) stream->info.rate = 11025; else stream->info.rate = shm->speed; stream->info.bits = shm->samplebits; stream->info.width = stream->info.bits / 8; stream->info.channels = shm->channels; if (S_XMP_StartPlay(stream) != 0) goto err2; /* percentual left/right channel separation, default is 70. */ if (stream->info.channels == 2) if (xmp_set_player(c, XMP_PLAYER_MIX, 100) != 0) goto err3; /* interpolation type, default is XMP_INTERP_LINEAR */ if (xmp_set_player(c, XMP_PLAYER_INTERP, XMP_INTERP_SPLINE) != 0) goto err3; return true; err3: xmp_end_player(c); err2: xmp_release_module(c); err1: xmp_free_context(c); return false; }
/** * Play music from the specified file. * * @param fileName Name of a file containing music data. */ void playMusic (const char * fileName) { File *file; unsigned char *psmData; int size; bool loadOk = false; #ifdef USE_MODPLUG ModPlug_Settings settings; #endif // Stop any existing music playing stopMusic(); // Load the music file try { file = new File(fileName, false); } catch (int e) { return; } // Find the size of the file size = file->getSize(); // Read the entire file into memory file->seek(0, true); psmData = file->loadBlock(size); delete file; #ifdef USE_MODPLUG // Set up libmodplug settings.mFlags = MUSIC_FLAGS; settings.mChannels = audioSpec.channels; if ((audioSpec.format == AUDIO_U8) || (audioSpec.format == AUDIO_S8)) settings.mBits = 8; else settings.mBits = 16; settings.mFrequency = audioSpec.freq; settings.mResamplingMode = MUSIC_RESAMPLEMODE; settings.mReverbDepth = 25; settings.mReverbDelay = 40; settings.mBassAmount = 50; settings.mBassRange = 10; settings.mSurroundDepth = 50; settings.mSurroundDelay = 40; settings.mLoopCount = -1; ModPlug_SetSettings(&settings); // Load the file into libmodplug musicFile = ModPlug_Load(psmData, size); loadOk = (musicFile != NULL); #elif defined(USE_XMP) // Load the file into libxmp loadOk = (xmp_load_module_from_memory(xmpC, psmData, size) == 0); #endif delete[] psmData; if (!loadOk) { logError("Could not play music file", fileName); return; } #ifdef USE_XMP int playerFlags = 0; if ((audioSpec.format == AUDIO_U8) || (audioSpec.format == AUDIO_S8)) playerFlags = playerFlags & XMP_FORMAT_8BIT; if ((audioSpec.format == AUDIO_U8) || (audioSpec.format == AUDIO_U16) || (audioSpec.format == AUDIO_U16MSB) || (audioSpec.format == AUDIO_U16LSB)) playerFlags = playerFlags & XMP_FORMAT_UNSIGNED; if (audioSpec.channels == 1) playerFlags = playerFlags & XMP_FORMAT_MONO; xmp_start_player(xmpC, audioSpec.freq, playerFlags); xmp_set_player(xmpC, XMP_PLAYER_INTERP, MUSIC_INTERPOLATION); # ifdef MUSIC_EFFECTS xmp_set_player(xmpC, XMP_PLAYER_DSP, MUSIC_EFFECTS); # endif #endif // Start the audio playing SDL_PauseAudio(0); return; }
UObject* USoundModImporterFactory::FactoryCreateBinary ( UClass* Class, UObject* InParent, FName Name, EObjectFlags Flags, UObject* Context, const TCHAR* FileType, const uint8*& Buffer, const uint8* BufferEnd, FFeedbackContext* Warn ) { // if the sound already exists, remember the user settings USoundMod* ExistingSound = FindObject<USoundMod>(InParent, *Name.ToString()); // TODO - Audio Threading. This needs to be sent to the audio device and wait on stopping the sounds TArray<UAudioComponent*> ComponentsToRestart; FAudioDevice* AudioDevice = GEngine->GetAudioDevice(); if (AudioDevice && ExistingSound) { // TODO: Generalize the stop sounds function //AudioDevice->StopSoundsForReimport(ExistingSound, ComponentsToRestart); } bool bUseExistingSettings = bSoundModFactorySuppressImportOverwriteDialog; if (ExistingSound && !bUseExistingSettings && !GIsAutomationTesting) { DisplayOverwriteOptionsDialog(FText::Format( NSLOCTEXT("SoundModImporterFactory", "ImportOverwriteWarning", "You are about to import '{0}' over an existing sound."), FText::FromName(Name))); switch (OverwriteYesOrNoToAllState) { case EAppReturnType::Yes: case EAppReturnType::YesAll: { // Overwrite existing settings bUseExistingSettings = false; break; } case EAppReturnType::No: case EAppReturnType::NoAll: { // Preserve existing settings bUseExistingSettings = true; break; } default: { FEditorDelegates::OnAssetPostImport.Broadcast(this, NULL); return NULL; } } } // Reset the flag back to false so subsequent imports are not suppressed unless the code explicitly suppresses it bSoundModFactorySuppressImportOverwriteDialog = false; TArray<uint8> RawModData; RawModData.Empty(BufferEnd - Buffer); RawModData.AddUninitialized(BufferEnd - Buffer); FMemory::Memcpy(RawModData.GetData(), Buffer, RawModData.Num()); // TODO: Validate that this is actually a mod file xmp_context xmpContext = xmp_create_context(); if (xmp_load_module_from_memory(xmpContext, RawModData.GetData(), RawModData.Num()) != 0) { return NULL; } xmp_module_info xmpModuleInfo; xmp_get_module_info(xmpContext, &xmpModuleInfo); // Use pre-existing sound if it exists and we want to keep settings, // otherwise create new sound and import raw data. USoundMod* Sound = (bUseExistingSettings && ExistingSound) ? ExistingSound : NewObject<USoundMod>(InParent, Name, Flags); Sound->Duration = xmpModuleInfo.seq_data->duration / 1000.f; xmp_release_module(xmpContext); xmp_free_context(xmpContext); Sound->RawData.Lock(LOCK_READ_WRITE); void* LockedData = Sound->RawData.Realloc(BufferEnd - Buffer); FMemory::Memcpy(LockedData, Buffer, BufferEnd - Buffer); Sound->RawData.Unlock(); FEditorDelegates::OnAssetPostImport.Broadcast(this, Sound); for (int32 ComponentIndex = 0; ComponentIndex < ComponentsToRestart.Num(); ++ComponentIndex) { ComponentsToRestart[ComponentIndex]->Play(); } return Sound; }