0
0

Hello am i a 4th year computing science student and i m looking for some help regarding Fmod.
I have started a project involving granular synthesis and i was reccommended to use fmod.
I am new to sound programming and any help would be greatly appreciated.
What i need help with is that i want to be able to take out very small (20ms) parts of several .wav files and combine them into a single .wav file.
Should I be using a Stream or a Sample? should i use the DSP features?
how can i access a specific point in a .wav?
I am using win xp.

  • You must to post comments
0
0

Looks like you want to lock the sample, read several bits of data from it, unlock the sample, and then combine these together in a separate buffer.

  • You must to post comments
0
0

Thanks for the help but i m still a bit unsure a about a few things
Say I wanted to copy the first 3ms of the sample to another buffer how would i do that?
Is what does each entry in the locked data that is returned by the function refere to in ms?

  • You must to post comments
0
0

Hi,
The record example I have in the fmod directory I downloaded doesn;t contain the part for writing to a wav file. Can someone please let me know where to get it. From reading other postings i believe it’s called saveTowave.

Thanks

  • You must to post comments
0
0

this is the code that is in the main.cpp file I have. It doesn’t have that function. Maybe I downloaded the worng file???

/*===============================================================================================
RECORD.EXE
Copyright (c), Firelight Technologies Pty, Ltd 1999-2003.

This example demonstrates some fundamental FMOD usage, loading and playing samples and a
music file, and calling some runtime manipulation and information functions.
===============================================================================================*/

include <windows.h>

include <commctrl.h>

include “resource.h”

include “common.h”

include “fmod.h”

include “fmod_errors.h”

define ID_RECORD 0x8801

define ID_PLAY 0x8802

define RECORDRATE 22050

define RECORDLEN (RECORDRATE * 5) /* 5 seconds at RECORDRATE khz */

TCHAR szAppName[] = L”RECORD”;
TCHAR szAppTitle[] = L”FMOD – record”;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

FSOUND_SAMPLE *samp = NULL;
int channel = -1;

/*
[
[DESCRIPTION]

[PARAMETERS]

[RETURN_VALUE]

[REMARKS]

[SEE_ALSO]

]
*/
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;

hInst = hInstance;

if (!Common_InitInstance(nCmdShow))
{
    return FALSE;
}

while (GetMessage(&amp;msg, NULL, 0, 0)) 
{
    TranslateMessage(&amp;msg);
    DispatchMessage(&amp;msg);
}

return msg.wParam;

}

/*
[
[DESCRIPTION]

[PARAMETERS]

[RETURN_VALUE]

[REMARKS]

[SEE_ALSO]

]
*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
static int text_y = 0;
int retrycount = 0;

switch (message) 
{
    case WM_CREATE :
    {
        Common_WM_CREATE(hWnd);

        while (!FSOUND_Init(32000, 32, 0) &amp;&amp; retrycount &lt; 10)
        {
            Sleep(100);
            retrycount++;
        }

        if (retrycount == 10)
        {
            Common_DisplayError();
        }
        else
        {
            samp = FSOUND_Sample_Alloc(FSOUND_UNMANAGED, RECORDLEN, FSOUND_STEREO | FSOUND_16BITS , RECORDRATE, 255, 128, 255);
            if (!samp)
            {
                Common_DisplayError();
                SendMessage(hWnd, WM_CLOSE, 0, 0);
                return 0;
            }
        }

        int y = 1;
        int bh = Common_GetButtonHeight(hWnd) + 1;
        Common_CreateButton(hWnd, L"Record", 0, y, -1, -1, ID_RECORD);
        Common_CreateButton(hWnd, L"Play", 0, y += bh, -1, -1, ID_PLAY);
        text_y = y + (bh * 2);

        break;
    }

    case WM_COMMAND :
    {
        wmId    = LOWORD(wParam); 
        wmEvent = HIWORD(wParam); 

        switch (wmId)
        {
            case IDM_HELP_ABOUT :
                Common_About(hWnd);
                break;
            case ID_RECORD :
                FSOUND_Record_StartSample(samp, FALSE);
                break;
            case ID_PLAY :
                FSOUND_Record_Stop();                   
                channel = FSOUND_PlaySound(FSOUND_FREE, samp);
                break;

            case IDM_FILE_EXIT :
                DestroyWindow(hWnd);
                break;

            default:
               return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    }

    case WM_TIMER :
        Common_WM_TIMER(hWnd);
        break;

    case WM_PAINT :
    {
        RECT rt;
        HDC hdc;
        PAINTSTRUCT ps;

        hdc = BeginPaint(hWnd, &amp;ps);
        GetClientRect(hWnd, &amp;rt);

        Common_SetTextY(text_y);
        Common_Printf(hdc, &amp;rt, "Record   Position %7d / %7d    ", FSOUND_Record_GetPosition(), FSOUND_Sample_GetLength(samp));
        Common_Printf(hdc, &amp;rt, "Playback Position %7d / %7d    ", FSOUND_GetCurrentPosition(channel), FSOUND_Sample_GetLength(samp));

        EndPaint(hWnd, &amp;ps);
        break;
    }

    case WM_CLOSE:
    case WM_DESTROY:
    {
        FSOUND_Sample_Free(samp);
        FSOUND_Close();

        Common_WM_CLOSE(hWnd);
        break;
    }
    default:
    {
        return DefWindowProc(hWnd, message, wParam, lParam);
    }

}
return 0;
}

  • You must to post comments
0
0

here’s what i would do, assuming that you are using C++.

The first step is to parse the .WAV file. Here is the code that does that (I’m not claiming that it is without errors but is working for me)

[code:1rpgta3e]

  /* this will eventually hold the WAVE data */
  short int * PCM; 

  /* string containing the path to your .WAV file */
  string filename = &quot;myWaveFile.wav&quot;;

  /* this tag tells us how data is encoded */
  unsigned short formatTag; 

  /* tells us whether WAVE is stereo or mono */                                         
  unsigned short channels;

  /* the playback rate */
  unsigned int sampleRate;

  /* data rate estimation */
  unsigned int avgBytesPerSec;

  /* number of bytes to a block */
  unsigned short blockAlignment;

  /* bit-depth */
  unsigned short bitsPerSample;

  /* Data size in bytes */
  long dataSize;

  /* Number of samples */
  long numSamples;

  ifstream WaveFile;

    WaveFile.open(filename.c_str(), ios_base::binary);

    /* check if given path points to a file */
    if ( WaveFile == NULL ) return;

    char ID[4];

    WaveFile.read(ID, 4);

    /* check if first four byte is string == RIFF */
    if ( compareRIFFID(ID, 1) == -1 ) return;

    long fileSize = 0;

    WaveFile.read((char*)&amp;fileSize, 4);

    WaveFile.read(ID, 4);

    /* check if we have the WAVE ID code */
    if ( compareRIFFID(ID, 2) == -1 ) return;

    WaveFile.read(ID, 4);

    /* check that we have the 'fmt ' ID */
    if ( compareRIFFID(ID, 3) == -1 ) return;

    long waveFormatInfo;

    WaveFile.read((char*)&amp;waveFormatInfo, 4);

    /* get all the wave file attributes */

    WaveFile.read((char*)&amp;formatTag, sizeof(unsigned short));

    WaveFile.read((char*)&amp;channels, sizeof(unsigned short));

    WaveFile.read((char*)&amp;sampleRate, sizeof(unsigned int));

    WaveFile.read((char*)&amp;avgBytesPerSec, sizeof(unsigned int));

    WaveFile.read((char*)&amp;blockAlignment, sizeof(unsigned short));

    WaveFile.read((char*)&amp;bitsPerSample, sizeof(unsigned short));

    WaveFile.read(ID, 4);

    /* check the 4th ID, the data ID */
    if ( compareRIFFID(ID, 4) == -1 ) return false;

    WaveFile.read((char*)&amp;dataSize, sizeof(long));

    if ( bitsPerSample == 16 ) numSamples = (dataSize / blockAlignment) * 2;

    void *soundData;

    soundData = (BYTE*) malloc (sizeof(BYTE) * dataSize);

    WaveFile.read((char*)soundData, dataSize);

    PCM = (short *) soundData; 

[/code:1rpgta3e]

so now all your data is contained in the array called PCM and its size is numSamples (this is the number of sound values it contains).

The above code uses a function called compareRIFFID (all it does is check for equality between 2 strings and I was to lazy to figure out how to do it efficiently and ended up making this function):

[code:1rpgta3e]
int Wave::compareRIFFID(char *ID, int code)
{
const char RIFF[] = { ‘R’, ‘I’, ‘F’, ‘F’ };
const char WAVE[] = { ‘W’, ‘A’, ‘V’, ‘E’ };
const char FORMAT[] = { ‘f’, ‘m’, ‘t’, ‘ ‘};
const char DATA[] = { ‘d’, ‘a’, ‘t’, ‘a’ };

    for (int i=0; i&lt;4; i++)
    {
    if ( code == 1 )
      if ( ID[i] != RIFF[i] ) return -1;
    if ( code == 2 )
      if ( ID[i] != WAVE[i] ) return -1;
    if ( code == 3 )
      if ( ID[i] != FORMAT[i] ) return -1;
    if ( code == 4 )
      if ( ID[i] != DATA[i] ) return -1;
    }

    return 1;
}

[/code:1rpgta3e]

Ok so now you want to take out chunks of 20ms from this WAVE file. Remember that the wave data itself is in the array called PCM and that the size of that array is numSamples. What you need is a buffer that will hold exactly 20 ms of data:

[code:1rpgta3e]

long bufferSize = ( 20 / 1000 ) * sampleRate;

short int * buffer;

buffer = new short int [ bufferSize ];

[/code:1rpgta3e]

the next step is to decide where from the WAVE file you want to read out 20 ms from. That is something dependant on your particular application but let us just suppose it is from index N onward.

[code:1rpgta3e]

for (long i=0; i<bufferSize; i++)
{
if ( i + N = numSamples ) break;
buffer [ i ] = PCM [ i + N ];
}
[/code:1rpgta3e]

Then you would fill this data into another bigger array repeatedly to construct the data for your output wave file.

To write to a WAVE file is another huge chunk of code I’m too tired to find but there’s an example in the fmod doc’s on how to do it.

I hope this helps.

PS: Fmod would have done all that in much less time but I’ve just gotten too attached to that code now :)

  • You must to post comments
Showing 5 results
Your Answer

Please first to submit.