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;
}
Exemple #3
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;

    /*
        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;
}
Exemple #4
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;
}