// Convert an 8 bit unsigned voice to the current rate. // Maintains unsignedness. void ConvertVoice8( Voice* InVoice ) { // How fast is this sample? INT VoiceRate = InVoice->pSample->SamplesPerSec; if ((VoiceRate != 11025) && (VoiceRate != 22050) && (VoiceRate != 44100)) appErrorf( TEXT("Unsupported playback rate: %i"), VoiceRate ); if (VoiceRate > AudioRate) { // This voice is slower than our current rate. INT RateFactor = VoiceRate / AudioRate; INT NewSize; if (InVoice->pSample->Length % 2 == 1) NewSize = (InVoice->pSample->Length+1) / RateFactor; else NewSize = InVoice->pSample->Length / RateFactor; BYTE* Source = (BYTE*) InVoice->pSample->Data; BYTE* NewData = (BYTE*) appMalloc(NewSize, TEXT("Sample Data")); check(NewData); BYTE* Dest = NewData; appMemset( Dest, 0x80, NewSize ); for (INT i=0; i<InVoice->pSample->Length; i += RateFactor) { *Dest = Source[i]; Dest++; } InVoice->PlayPosition = 0; InVoice->pSample->SamplesPerSec = AudioRate; InVoice->pSample->Length = NewSize; void* OldData = InVoice->pSample->Data; InVoice->pSample->Data = NewData; appFree( OldData ); } else { // This voice is faster than our current rate. INT RateFactor = AudioRate / VoiceRate; INT NewSize = InVoice->pSample->Length * RateFactor; BYTE* Source = (BYTE*) InVoice->pSample->Data; BYTE* NewData = (BYTE*) appMalloc(NewSize, TEXT("Sample Data")); check(NewData); BYTE* Dest = NewData; appMemset( Dest, 0x80, NewSize ); for (INT i=0; i<NewSize; i++) { Dest[i] = *Source; if (i%RateFactor == 1) Source++; } InVoice->PlayPosition = 0; InVoice->pSample->SamplesPerSec = AudioRate; InVoice->pSample->Length = NewSize; void* OldData = InVoice->pSample->Data; InVoice->pSample->Data = (void*) NewData; appFree( OldData ); } }
void* DoSound(void* Arguments) { // Allocate the mixing buffer. ALock; MixBuffer = appMalloc(BufferSize, TEXT("Mixing Buffer")); AUnlock; INT Task = SOUND_MIXING, i; while (MixingThread.Valid) { switch (Task) { case SOUND_MIXING: ALock; // Empty the mixing buffer. appMemset(MixBuffer, 0, BufferSize); for (i=0; i<AUDIO_TOTALVOICES; i++) { // Get an enabled and active voice. if ((Voices[i].State&VOICE_ENABLED) && (Voices[i].State&VOICE_ACTIVE) && !AudioPaused) { // Mix a buffer's worth of sound. INT Format = Voices[i].pSample->Type & SAMPLE_16BIT ? SAMPLE_16BIT : SAMPLE_8BIT; switch (Format) { case SAMPLE_8BIT: if (AudioFormat & AUDIO_16BIT) MixVoice8to16( i ); break; case SAMPLE_16BIT: if (AudioFormat & AUDIO_16BIT) MixVoice16to16( i ); break; } } } AUnlock; Task = SOUND_PLAYING; break; case SOUND_PLAYING: // Block until the audio device is writable. if (!AudioPaused) { if (AudioWait() == 0) break; } else break; ALock; // Silence the audio buffer. appMemset(AudioBuffer, 0, BufferSize); // Ready the most recently mixed audio. appMemcpy(AudioBuffer, MixBuffer, BufferSize); // Play it. if (!AudioPaused) { PlayAudio(); } AUnlock; Task = SOUND_MIXING; break; } } // Free the mixing buffer. ALock; if (MixBuffer != NULL) appFree(MixBuffer); AUnlock; ExitAudioThread(&MixingThread); }
void USwFMOD::RegisterMusic( UMusic* Music ) { guard(USwFMOD::RegisterMusic); //SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: [%s]"), SWF_LOGP, *ToStr(Music) ); FMOD_RESULT result; checkSlow(Music); if( !Music->Handle ) { FMOD::Sound* sound; // Load the data. Music->Data.Load(); SWF_LOG( NAME_DevSound, TEXT("Register music: %s (%i)"), Music->GetPathName(), Music->Data.Num() ); check(Music->Data.Num()>0); // Sound extended data #pragma pack(push) #pragma pack(8) FMOD_CREATESOUNDEXINFO exinfo; appMemset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); exinfo.length = Music->Data.Num(); #pragma pack(pop) // Sound flags FMOD_MODE fmode = 0 | FMOD_SOFTWARE // | FMOD_IGNORETAGS // | FMOD_LOOP_NORMAL | FMOD_2D | FMOD_OPENMEMORY // | FMOD_ACCURATETIME | FMOD_CREATESTREAM ; // Format-specific flags if( Music->FileType == SoundType_OGG ) { exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_OGGVORBIS; fmode |= FMOD_LOOP_NORMAL; } else if( Music->FileType == SoundType_MP2 || Music->FileType == SoundType_MP3 ) { exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_MPEG; fmode |= FMOD_LOOP_NORMAL; } else { } // Create sound SWF_FMOD_CALL( System->createStream( static_cast<const char*>(Music->Data.GetData()), fmode, &exinfo, &sound )); if( result == FMOD_OK ) { // Register the sound. Music->Handle = sound; SWF_FMOD_CALL( sound->setUserData(Music) ); } else { SWF_LOG_WARN( FString::Printf(TEXT("Couldn't register music [%s][%i][%s]"), Music->GetPathName(), Music->Data.Num(), *ToStr(result)) ); } // Do not unload yet. //Music->Data.Unload(); } unguard; }
void USwFMOD::RegisterSound( USound* Sound ) { guard(USwFMOD::RegisterSound); //SWF_LOG( NAME_DevSound, TEXT("%s -- %s :: [%s]"), SWF_LOGP, *ToStr(Sound) ); FMOD_RESULT result; checkSlow(Sound); if( !Sound->Handle ) { FMOD::Sound* sound; // Load the data. Sound->Data.LoadSpecial(); SWF_LOG( NAME_DevSound, TEXT("Register sound: %s (%i)"), Sound->GetPathName(), Sound->Data.Num() ); check(Sound->Data.Num()>0); // Sound extended data #pragma pack(push) #pragma pack(8) FMOD_CREATESOUNDEXINFO exinfo; appMemset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); exinfo.length = Sound->Data.Num(); #pragma pack(pop) // Sound flags FMOD_MODE fmode = 0 | FMOD_SOFTWARE | FMOD_IGNORETAGS // | FMOD_LOOP_OFF // | FMOD_2D | FMOD_OPENMEMORY | FMOD_CREATESAMPLE | FMOD_3D | FMOD_3D_LINEARROLLOFF ; // Format-specific flags if( Sound->FileType == SoundType_WAV ) { // WAV exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; } else if( Sound->FileType == SoundType_MP2 || Sound->FileType == SoundType_MP3 ) { // MP3 fmode |= FMOD_ACCURATETIME; exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_MPEG; } else { // Unknown, try anyway fmode |= FMOD_ACCURATETIME; } // Create sound SWF_FMOD_CALL( System->createSound( static_cast<const char*>(Sound->Data.GetData()), fmode, &exinfo, &sound )); if( result == FMOD_OK ) { // Register the sound. Sound->Handle = sound; SWF_FMOD_CALL( sound->setUserData(Sound) ); unsigned int length; SWF_FMOD_CALL( sound->getLength(&length,FMOD_TIMEUNIT_MS) ); Sound->Duration = length*0.001f; } else { SWF_LOG_WARN( FString::Printf(TEXT("Couldn't register sound [%s][%i][%s]"), Sound->GetPathName(), Sound->Data.Num(), *ToStr(result)) ); } // Unload the data. Sound->Data.Unload(); } unguard; }
/* ---------------------------------------------------------------------------- USwFMOD ---------------------------------------------------------------------------- */ void USwFMOD::DumpSystem() { guard(USwFMOD::DumpSystem); FMOD_RESULT result; FString text; if( !System ) return; // // pre-init // #pragma pack(push) #pragma pack(8) FMOD_ADVANCEDSETTINGS adv; appMemset(&adv, 0, sizeof(FMOD_ADVANCEDSETTINGS)); adv.cbsize = sizeof(FMOD_ADVANCEDSETTINGS); #pragma pack(pop) FMOD_OUTPUTTYPE output; int driveridx; int softchan; int samplerate; FMOD_SOUND_FORMAT format; int numoutputchannels; int maxinputchannels; FMOD_DSP_RESAMPLER resamplemethod; int bits; unsigned int bufferlength; int numbuffers; FMOD_SPEAKERMODE speakermode; /* char drivername[1024]; FMOD_CAPS caps; INT minfreq, maxfreq; FMOD_SPEAKERMODE smode;*/ SWF_FMOD_CALL( System->getOutput(&output) ); // SWF_FMOD_CALL( System->getNumDrivers() ); // SWF_FMOD_CALL( System->getDriverName() ); // SWF_FMOD_CALL( System->getDriverCaps() ); SWF_FMOD_CALL( System->getDriver(&driveridx) ); SWF_FMOD_CALL( System->getSoftwareChannels(&softchan) ); SWF_FMOD_CALL( System->getSoftwareFormat(&samplerate,&format,&numoutputchannels,&maxinputchannels,&resamplemethod,&bits) ); SWF_FMOD_CALL( System->getDSPBufferSize(&bufferlength,&numbuffers) ); SWF_FMOD_CALL( System->getAdvancedSettings(&adv) ); SWF_FMOD_CALL( System->getSpeakerMode(&speakermode) ); SWF_LOG_DEV_STATIC( System->getOutput, SWF_STSTR(output) ); SWF_LOG_DEV_STATIC( System->getDriver, SWF_STSTR(driveridx) ); SWF_LOG_DEV_STATIC( System->getSoftwareChannels, SWF_STSTR(softchan) ); SWF_LOG_DEV_STATIC( System->getSoftwareFormat, SWF_STSTR(samplerate) + SWF_STSTR(format) + SWF_STSTR(numoutputchannels) + SWF_STSTR(maxinputchannels) + SWF_STSTR(resamplemethod) + SWF_STSTR(bits) ); SWF_LOG_DEV_STATIC( System->getDSPBufferSize, SWF_STSTR(bufferlength) + SWF_STSTR(numbuffers) ); SWF_LOG_DEV_STATIC( System->getAdvancedSettings, SWF_STSTR(adv) ); SWF_LOG_DEV_STATIC( System->getSpeakerMode, SWF_STSTR(speakermode) ); /* // Driver int idx = 0; SWF_FMOD_CALL( System->getDriverName( idx, drivername, 1024) ); SWF_FMOD_CALL( System->getDriverCaps( idx, &caps, &minfreq, &maxfreq, &smode ) ); SWF_LOG( SWF_NAME, TEXT("Driver: %s"), *ToStr(appFromAnsi(drivername)) ); SWF_LOG( SWF_NAME, TEXT("Driver Frequency: %d - %d"), minfreq, maxfreq ); SWF_LOG( SWF_NAME, TEXT("Driver Caps: %s"), *FMOD_CAPSToStr(caps) ); SWF_LOG( SWF_NAME, TEXT("Driver Speaker Mode: %s"), *FMOD_SPEAKERMODEToStr(smode) );*/ // // System information functions. // FSwVersion version; int num2d; int num3d; int hctotal; int currentalloced; int maxalloced; int memtotal; SWF_FMOD_CALL( System->getVersion(version.GetRaw()) ); // SWF_FMOD_CALL( System->getOutputHandle(&version) ); // SWF_FMOD_CALL( System->getChannelsPlaying(&version) ); SWF_FMOD_CALL( System->getHardwareChannels(&num2d,&num3d,&hctotal) ); // SWF_FMOD_CALL( System->getCPUUsage(&version) ); SWF_FMOD_CALL( System->getSoundRAM(¤talloced,&maxalloced,&memtotal) ); // SWF_FMOD_CALL( System->getNumCDROMDrives(&version) ); // SWF_FMOD_CALL( System->getCDROMDriveName(&version) ); // SWF_FMOD_CALL( System->getSpectrum(&version) ); // SWF_FMOD_CALL( System->getWaveData(&version) ); SWF_LOG_DEV_STATIC( System->getVersion, SWF_STSTR(version) ); SWF_LOG_DEV_STATIC( System->getHardwareChannels, SWF_STSTR(num2d) + SWF_STSTR(num3d) + SWF_STSTR(hctotal) ); SWF_LOG_DEV_STATIC( System->getSoundRAM, SWF_STSTR(currentalloced) + SWF_STSTR(maxalloced) + SWF_STSTR(memtotal)); // // post-init // float dopplerscale; float distancefactor; float rolloffscale; SWF_FMOD_CALL( System->get3DSettings(&dopplerscale,&distancefactor,&rolloffscale) ); SWF_LOG_DEV_STATIC( System->get3DSettings, SWF_STSTR(dopplerscale) + SWF_STSTR(distancefactor) + SWF_STSTR(rolloffscale) ); unguard; }