SPtr<Resource> FMODImporter::import(const Path& filePath, SPtr<const ImportOptions> importOptions) { WString extension = filePath.getWExtension(); StringUtil::toLowerCase(extension); AudioFileInfo info; FMOD::Sound* sound; String pathStr = filePath.toString(); if(gFMODAudio()._getFMOD()->createSound(pathStr.c_str(), FMOD_CREATESAMPLE, nullptr, &sound) != FMOD_OK) { LOGERR("Failed importing audio file: " + pathStr); return nullptr; } FMOD_SOUND_FORMAT format; INT32 numChannels = 0; INT32 numBits = 0; sound->getFormat(nullptr, &format, &numChannels, &numBits); if(format != FMOD_SOUND_FORMAT_PCM8 && format != FMOD_SOUND_FORMAT_PCM16 && format != FMOD_SOUND_FORMAT_PCM24 && format != FMOD_SOUND_FORMAT_PCM32 && format != FMOD_SOUND_FORMAT_PCMFLOAT) { LOGERR("Failed importing audio file, invalid imported format: " + pathStr); return nullptr; } float frequency = 0.0f; sound->getDefaults(&frequency, nullptr); UINT32 size; sound->getLength(&size, FMOD_TIMEUNIT_PCMBYTES); info.bitDepth = numBits; info.numChannels = numChannels; info.sampleRate = (UINT32)frequency; info.numSamples = size / (info.bitDepth / 8); UINT32 bytesPerSample = info.bitDepth / 8; UINT32 bufferSize = info.numSamples * bytesPerSample; UINT8* sampleBuffer = (UINT8*)bs_alloc(bufferSize); assert(bufferSize == size); UINT8* startData = nullptr; UINT8* endData = nullptr; UINT32 startSize = 0; UINT32 endSize = 0; sound->lock(0, size, (void**)&startData, (void**)&endData, &startSize, &endSize); if(format == FMOD_SOUND_FORMAT_PCMFLOAT) { assert(info.bitDepth == 32); UINT32* output = (UINT32*)sampleBuffer; for(UINT32 i = 0; i < info.numSamples; i++) { float value = *(((float*)startData) + i); *output = (UINT32)(value * 2147483647.0f); output++; } } else { memcpy(sampleBuffer, startData, bufferSize); } sound->unlock((void**)&startData, (void**)&endData, startSize, endSize); sound->release(); SPtr<const AudioClipImportOptions> clipIO = std::static_pointer_cast<const AudioClipImportOptions>(importOptions); // If 3D, convert to mono if (clipIO->getIs3D() && info.numChannels > 1) { UINT32 numSamplesPerChannel = info.numSamples / info.numChannels; UINT32 monoBufferSize = numSamplesPerChannel * bytesPerSample; UINT8* monoBuffer = (UINT8*)bs_alloc(monoBufferSize); AudioUtility::convertToMono(sampleBuffer, monoBuffer, info.bitDepth, numSamplesPerChannel, info.numChannels); info.numSamples = numSamplesPerChannel; info.numChannels = 1; bs_free(sampleBuffer); sampleBuffer = monoBuffer; bufferSize = monoBufferSize; } // Convert bit depth if needed if (clipIO->getBitDepth() != info.bitDepth) { UINT32 outBufferSize = info.numSamples * (clipIO->getBitDepth() / 8); UINT8* outBuffer = (UINT8*)bs_alloc(outBufferSize); AudioUtility::convertBitDepth(sampleBuffer, info.bitDepth, outBuffer, clipIO->getBitDepth(), info.numSamples); info.bitDepth = clipIO->getBitDepth(); bs_free(sampleBuffer); sampleBuffer = outBuffer; bufferSize = outBufferSize; } // Encode to Ogg Vorbis if needed if (clipIO->getFormat() == AudioFormat::VORBIS) { // TODO - Encode to Ogg Vorbis! } SPtr<MemoryDataStream> sampleStream = bs_shared_ptr_new<MemoryDataStream>(sampleBuffer, bufferSize); AUDIO_CLIP_DESC clipDesc; clipDesc.bitDepth = info.bitDepth; clipDesc.format = clipIO->getFormat(); clipDesc.frequency = info.sampleRate; clipDesc.numChannels = info.numChannels; clipDesc.readMode = clipIO->getReadMode(); clipDesc.is3D = clipIO->getIs3D(); SPtr<AudioClip> clip = AudioClip::_createPtr(sampleStream, bufferSize, info.numSamples, clipDesc); WString fileName = filePath.getWFilename(false); clip->setName(fileName); return clip; }
void FMODVoiceAdapter::UpdateSound(bool isRec) { FMOD_RESULT fmodErr; unsigned int soundLength; const int sampleSize = 2; FMOD::Sound *snd = (isRec) ? recSound : sound; unsigned int& lastPos = (isRec) ? lastRecordingPos : lastPlayPos; // get current Play or recording position unsigned int currPos; if (isRec){ fmodErr=fmodSystem->getRecordPosition(0,&currPos); RakAssert(fmodErr==FMOD_OK); } else { fmodErr=channel->getPosition(&currPos, FMOD_TIMEUNIT_PCM); RakAssert(fmodErr==FMOD_OK); } // Get length of sound in samples fmodErr=snd->getLength(&soundLength, FMOD_TIMEUNIT_PCM); RakAssert(fmodErr==FMOD_OK); // calculate some variables we'll need ahead int bufferSizeBytes = rakVoice->GetBufferSizeBytes(); // Round down the current position to a multiple of buffer size in samples currPos -= currPos % (bufferSizeBytes/sampleSize); if ( ((!isRec)||(isRec && !mute)) && (currPos != lastPos) ) { void *ptr1, *ptr2; unsigned int len1, len2; int blockLength; blockLength = (int)currPos - (int)lastPos; // Check for wrap around, and adjust if (blockLength < 0) { blockLength += soundLength; } // Lock to get access to the raw data snd->lock(lastPos * sampleSize, blockLength * sampleSize, &ptr1, &ptr2, &len1, &len2); // Since the length and current position are both a multiple of bufferSizeBytes // just treat treat one full buffer at a time int numFrames = len1 / bufferSizeBytes; while(numFrames--){ if (isRec) { BroadcastFrame(ptr1); } else { rakVoice->ReceiveFrame(ptr1); } ptr1 = (char*)ptr1 + bufferSizeBytes; } numFrames = len2 / bufferSizeBytes; while(numFrames--) { if (isRec){ BroadcastFrame(ptr2); } else { rakVoice->ReceiveFrame(ptr2); } ptr2 = (char*)ptr2 + bufferSizeBytes; } snd->unlock(ptr1, ptr2, len1, len2); } lastPos = currPos; }
int main(int argc, char *argv[]) { FMOD::System *system = 0; FMOD::Sound *sound = 0; FMOD_RESULT result; FMOD_CREATESOUNDEXINFO exinfo; int key, recorddriver, numdrivers, count; unsigned int version; FILE *fp; unsigned int datalength = 0, soundlength; /* Create a System object and initialize. */ result = FMOD::System_Create(&system); ERRCHECK(result); result = system->getVersion(&version); ERRCHECK(result); if (version < FMOD_VERSION) { printf("Error! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION); return 0; } /* System initialization */ printf("---------------------------------------------------------\n"); printf("Select OUTPUT type\n"); printf("---------------------------------------------------------\n"); printf("1 : DirectSound\n"); printf("2 : Windows Multimedia WaveOut\n"); printf("3 : ASIO\n"); printf("---------------------------------------------------------\n"); printf("Press a corresponding number or ESC to quit\n"); do { key = _getch(); } while (key != 27 && key < '1' && key > '5'); switch (key) { case '1' : result = system->setOutput(FMOD_OUTPUTTYPE_DSOUND); break; case '2' : result = system->setOutput(FMOD_OUTPUTTYPE_WINMM); break; case '3' : result = system->setOutput(FMOD_OUTPUTTYPE_ASIO); break; default : return 1; } ERRCHECK(result); /* Enumerate record devices */ result = system->getRecordNumDrivers(&numdrivers); ERRCHECK(result); printf("---------------------------------------------------------\n"); printf("Choose a RECORD driver\n"); printf("---------------------------------------------------------\n"); for (count=0; count < numdrivers; count++) { char name[256]; result = system->getRecordDriverInfo(count, name, 256, 0); ERRCHECK(result); printf("%d : %s\n", count + 1, name); } printf("---------------------------------------------------------\n"); printf("Press a corresponding number or ESC to quit\n"); recorddriver = 0; do { key = _getch(); if (key == 27) { return 0; } recorddriver = key - '1'; } while (recorddriver < 0 || recorddriver >= numdrivers); printf("\n"); result = system->init(32, FMOD_INIT_NORMAL, 0); ERRCHECK(result); memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); exinfo.numchannels = 1; exinfo.format = FMOD_SOUND_FORMAT_PCM16; exinfo.defaultfrequency = 44100; exinfo.length = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * 2; result = system->createSound(0, FMOD_2D | FMOD_SOFTWARE | FMOD_OPENUSER, &exinfo, &sound); ERRCHECK(result); printf("========================================================================\n"); printf("Record to disk example. Copyright (c) Firelight Technologies 2004-2014.\n"); printf("========================================================================\n"); printf("\n"); printf("Press a key to start recording to record.wav\n"); printf("\n"); _getch(); result = system->recordStart(recorddriver, sound, true); ERRCHECK(result); printf("Press 'Esc' to quit\n"); printf("\n"); fp = fopen("record.wav", "wb"); if (!fp) { printf("ERROR : could not open record.wav for writing.\n"); return 1; } /* Write out the wav header. As we don't know the length yet it will be 0. */ WriteWavHeader(fp, sound, datalength); result = sound->getLength(&soundlength, FMOD_TIMEUNIT_PCM); ERRCHECK(result); /* Main loop. */ do { static unsigned int lastrecordpos = 0; unsigned int recordpos = 0; if (_kbhit()) { key = _getch(); } system->getRecordPosition(recorddriver, &recordpos); ERRCHECK(result); if (recordpos != lastrecordpos) { void *ptr1, *ptr2; int blocklength; unsigned int len1, len2; blocklength = (int)recordpos - (int)lastrecordpos; if (blocklength < 0) { blocklength += soundlength; } /* Lock the sound to get access to the raw data. */ sound->lock(lastrecordpos * exinfo.numchannels * 2, blocklength * exinfo.numchannels * 2, &ptr1, &ptr2, &len1, &len2); /* * exinfo.numchannels * 2 = stereo 16bit. 1 sample = 4 bytes. */ /* Write it to disk. */ if (ptr1 && len1) { datalength += fwrite(ptr1, 1, len1, fp); } if (ptr2 && len2) { datalength += fwrite(ptr2, 1, len2, fp); } /* Unlock the sound to allow FMOD to use it again. */ sound->unlock(ptr1, ptr2, len1, len2); } lastrecordpos = recordpos; printf("%-23s. Record buffer pos = %6d : Record time = %02d:%02d\r", (timeGetTime() / 500) & 1 ? "Recording to record.wav" : "", recordpos, datalength / exinfo.defaultfrequency / exinfo.numchannels / 2 / 60, (datalength / exinfo.defaultfrequency / exinfo.numchannels / 2) % 60); system->update(); Sleep(10); } while (key != 27); printf("\n"); /* Write back the wav header now that we know its length. */ WriteWavHeader(fp, sound, datalength); fclose(fp); /* Shut down */ result = sound->release(); ERRCHECK(result); result = system->release(); ERRCHECK(result); return 0; }
int main(int argc, char *argv[]) { FMOD::System *system = 0; FMOD::Sound *sound = 0; FMOD_RESULT result; FMOD_CREATESOUNDEXINFO exinfo; int key, recorddriver, numdrivers, count; unsigned int version; FILE *fp; unsigned int datalength = 0, soundlength; bool iscoreaudio = false; /* Create a System object and initialize. */ result = FMOD::System_Create(&system); ERRCHECK(result); result = system->getVersion(&version); ERRCHECK(result); if (version < FMOD_VERSION) { printf("Error! You are using an old version of FMOD %08x. This program requires %08x\n", version, FMOD_VERSION); return 0; } result = system->setOutput(FMOD_OUTPUTTYPE_COREAUDIO); ERRCHECK(result); /* Enumerate record devices */ result = system->getRecordNumDrivers(&numdrivers); ERRCHECK(result); printf("---------------------------------------------------------\n"); printf("Choose a RECORD driver\n"); printf("---------------------------------------------------------\n"); for (count=0; count < numdrivers; count++) { char name[256]; result = system->getRecordDriverInfo(count, name, 256, 0); ERRCHECK(result); printf("%d : %s\n", count + 1, name); } printf("---------------------------------------------------------\n"); printf("Press a corresponding number or ESC to quit\n"); recorddriver = 0; do { key = getch(); if (key == 27) { return 0; } recorddriver = key - '1'; } while (recorddriver < 0 || recorddriver >= numdrivers); printf("\n"); result = system->init(32, FMOD_INIT_NORMAL, 0); ERRCHECK(result); memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO)); exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO); exinfo.numchannels = 2; exinfo.defaultfrequency = 44100; if (iscoreaudio) { exinfo.format = FMOD_SOUND_FORMAT_PCMFLOAT; exinfo.length = exinfo.defaultfrequency * sizeof(float) * exinfo.numchannels * 2; } else { exinfo.format = FMOD_SOUND_FORMAT_PCM16; exinfo.length = exinfo.defaultfrequency * sizeof(short) * exinfo.numchannels * 2; } result = system->createSound(0, FMOD_2D | FMOD_SOFTWARE | FMOD_OPENUSER, &exinfo, &sound); ERRCHECK(result); printf("========================================================================\n"); printf("Record to disk example. Copyright (c) Firelight Technologies 2004-2014.\n"); printf("========================================================================\n"); printf("\n"); printf("Press a key to start recording to record.wav\n"); printf("\n"); getch(); result = system->recordStart(recorddriver, sound, true); ERRCHECK(result); printf("Press 'Esc' to quit\n"); printf("\n"); fp = fopen("record.wav", "wb"); if (!fp) { printf("ERROR : could not open record.wav for writing.\n"); return 1; } /* Write out the wav header. As we don't know the length yet it will be 0. */ WriteWavHeader(fp, sound, datalength); result = sound->getLength(&soundlength, FMOD_TIMEUNIT_PCM); ERRCHECK(result); /* Main loop. */ do { static unsigned int lastrecordpos = 0; unsigned int recordpos = 0; if (kbhit()) { key = getch(); } system->getRecordPosition(recorddriver, &recordpos); ERRCHECK(result); if (recordpos != lastrecordpos) { void *ptr1, *ptr2; int blocklength; unsigned int len1, len2; blocklength = (int)recordpos - (int)lastrecordpos; if (blocklength < 0) { blocklength += soundlength; } /* Lock the sound to get access to the raw data. */ if(iscoreaudio) { sound->lock(lastrecordpos * 8, blocklength * 8, &ptr1, &ptr2, &len1, &len2); /* *8 = stereo 32bit. 1 sample = 8 bytes. */ } else { sound->lock(lastrecordpos * 4, blocklength * 4, &ptr1, &ptr2, &len1, &len2); /* *4 = stereo 16bit. 1 sample = 4 bytes. */ } /* Write it to disk. */ if (ptr1 && len1) { #ifdef __BIG_ENDIAN__ if (exinfo.format == FMOD_SOUND_FORMAT_PCM16) { signed short *wptr = (signed short *)ptr1; for (int count = 0; count < len1 >> 1; count++) { wptr[count] = SWAPENDIAN_WORD(wptr[count]); } } else if (exinfo.format == FMOD_SOUND_FORMAT_PCMFLOAT) { float *fptr = (float *)ptr1; for (int count = 0; count < len1 >> 2; count++) { SWAPENDIAN_FLOAT(fptr[count]); } } #endif datalength += fwrite(ptr1, 1, len1, fp); } if (ptr2 && len2) { #ifdef __BIG_ENDIAN__ if (exinfo.format == FMOD_SOUND_FORMAT_PCM16) { signed short *wptr = (signed short *)ptr2; for (int count = 0; count < len2 >> 1; count++) { wptr[count] = SWAPENDIAN_WORD(wptr[count]); } } else if (exinfo.format == FMOD_SOUND_FORMAT_PCMFLOAT) { float *fptr = (float *)ptr2; for (int count = 0; count < len2 >> 2; count++) { SWAPENDIAN_FLOAT(fptr[count]); } } #endif datalength += fwrite(ptr2, 1, len2, fp); } /* Unlock the sound to allow FMOD to use it again. */ sound->unlock(ptr1, ptr2, len1, len2); } lastrecordpos = recordpos; printf("\rRecord buffer pos = %6d : Record time = %02d:%02d", recordpos, datalength / exinfo.defaultfrequency / 4 / 60, (datalength / exinfo.defaultfrequency / 4) % 60); fflush(stdout); system->update(); Sleep(10); } while (key != 27); printf("\n"); /* Write back the wav header now that we know its length. */ WriteWavHeader(fp, sound, datalength); fclose(fp); /* Shut down */ result = sound->release(); ERRCHECK(result); result = system->release(); ERRCHECK(result); return 0; }