Answered
0
0

Hi,
I want to record sound and save to a .wav file. But when i use system->setOutput(FMOD_OUTPUTTYPE_WAVWRITER). getRecordNumDrivers return 0, so i cant record sound, Could anyone please tell me how to record sound and save to .wav file? What’s the problem in my code?

thanks,

xq

  • You must to post comments
Best Answer
0
1

When you select an output mode you control which interface with sound devices you have. Unfortunately input (recording) and output are tied together. So if you choose wav writer output there is no interface for microphone recording.

We have a Windows example from FMOD 4 called ‘record to disk’ that shows how to do this. I’ll include the sample code here, it might need some minor tweaks for FMOD 5 compatibility.

/*===============================================================================================
Record to disk example
Copyright (c), Firelight Technologies Pty, Ltd 2004-2015.

This example shows how to do a streaming record to disk.
===============================================================================================*/
#include <windows.h>
#include <stdio.h>
#include <conio.h>

#include "../../api/inc/fmod.hpp"
#include "../../api/inc/fmod_errors.h"

void ERRCHECK(FMOD_RESULT result)
{
    if (result != FMOD_OK)
    {
        printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
        exit(-1);
    }
}

#if defined(WIN32) || defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__)
    #define __PACKED                         /* dummy */
#else
    #define __PACKED __attribute__((packed)) /* gcc packed */
#endif


/*
[
    [DESCRIPTION]
    Writes out the contents of a record buffer to a file.

    [PARAMETERS]

    [RETURN_VALUE]
    void

    [REMARKS]
]
*/
void WriteWavHeader(FILE *fp, FMOD::Sound *sound, int length)
{
    int             channels, bits;
    float           rate;

    if (!sound)
    {
        return;
    }

    fseek(fp, 0, SEEK_SET);

    sound->getFormat  (0, 0, &channels, &bits);
    sound->getDefaults(&rate, 0, 0, 0);

    {
        #if defined(WIN32) || defined(_WIN64) || defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__)
        #pragma pack(1)
        #endif

        /*
            WAV Structures
        */
        typedef struct
        {
            signed char id[4];
            int         size;
        } RiffChunk;

        struct
        {
            RiffChunk       chunk           __PACKED;
            unsigned short  wFormatTag      __PACKED;    /* format type  */
            unsigned short  nChannels       __PACKED;    /* number of channels (i.e. mono, stereo...)  */
            unsigned int    nSamplesPerSec  __PACKED;    /* sample rate  */
            unsigned int    nAvgBytesPerSec __PACKED;    /* for buffer estimation  */
            unsigned short  nBlockAlign     __PACKED;    /* block size of data  */
            unsigned short  wBitsPerSample  __PACKED;    /* number of bits per sample of mono data */
        } FmtChunk  = { {{'f','m','t',' '}, sizeof(FmtChunk) - sizeof(RiffChunk) }, 1, channels, (int)rate, (int)rate * channels * bits / 8, 1 * channels * bits / 8, bits } __PACKED;

        struct
        {
            RiffChunk   chunk;
        } DataChunk = { {{'d','a','t','a'}, length } };

        struct
        {
            RiffChunk   chunk;
            signed char rifftype[4];
        } WavHeader = { {{'R','I','F','F'}, sizeof(FmtChunk) + sizeof(RiffChunk) + length }, {'W','A','V','E'} };

        #if defined(WIN32) || defined(_WIN64) || defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__)
        #pragma pack()
        #endif

        /*
            Write out the WAV header.
        */
        fwrite(&WavHeader, sizeof(WavHeader), 1, fp);
        fwrite(&FmtChunk, sizeof(FmtChunk), 1, fp);
        fwrite(&DataChunk, sizeof(DataChunk), 1, fp);
    }
}


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-2015.\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;
}
  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.