0
0

hello!

im trying to apply a dsp effect to live voice input. i’ve used some of the csharp v2005 pitchdetection example to retrieve live voice input (creates a sound, records to it and then plays it back after sleep(200)). see below:

[code:3hkb44qc]
/*Start recording */
result = system.recordStart(selected, sound, true);
ERRCHECK(result);

        Thread.Sleep(200);      /* Give it some time to record something */

        result = system.playSound(FMOD.CHANNELINDEX.REUSE, sound, false, ref channel);
        ERRCHECK(result);

        result = system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel);
        ERRCHECK(result);

        /* Dont hear what is being recorded otherwise it will feedback.  Spectrum analysis is done before volume scaling in the DSP chain */
        result = channel.setVolume(0.5f);
        ERRCHECK(result);

[/code:3hkb44qc]

i want to apply an effect so that the output from the microphone is modified. for example a square wave oscillator tone thingy =P any tips would be much appriciated, i’m very new to FMod!

  • You must to post comments
0
0

Hi Dilek,

the filters mentioned on that wikipedia page are Infinite Impulse Response filters (IIR). Basically the DSP equivalent of a simple analog circuit. Another way of representing the filter is like so:

y[0] = a[0]x[0] + a[1]x[1] – y[1]*b[1]

Where y is your output samples and x is your input samples.

You have four coefficients: a0, a1, b1. (technically four, but b0 always is exactly 1.0 so it’s optimised away from the above expression).

These filters have very interesting phase properties.

For this reason, I would highly recommend NOT doing this:

sample = get_sample_from_stream
sample_low = apply_low_pass_filter(sample)
sample_high = apply_high_pass_filter(sample)
output_sample = low_gain * sample_low + high_gain * sample_high.

This will give you very strange results, including complete frequency cancellation do to phasing near the filter frequency.

If you want to use IIR filters, then I’d look at combining SHELF filters and BAND PASS filters.

I read a great book by W. Stanley – first written in the 1970’s.!!!

http://www.amazon.com/Digital-Signal-Pr … 083591321X

Good luck!

  • You must to post comments
0
0

ok so this should be the bands that are required, an array of 16:

[code:ayc9x1k5]octave1:
500-625
625-750
750-875
875-1000

octave2:
1000-1250
1250-1500
1500-1750
1750-2000

octave3:
2000-2500
2500-3000
3000-3500
3500-4000

octave4:
4000-5000
5000-6000
6000-7000
7000-8000[/code:ayc9x1k5]

which type of array can store the bands? and what type exactly is a band?

[quote:ayc9x1k5]the ‘spectrumarray’ returned from getSpectrum contains floats between 0.0 and 1.0 for each frequency band. The frequency bands might not be the same as the ones you want. [/quote:ayc9x1k5]

how does the getspectrum method return for each frequnecy band? i thought it just returns for the entire spectrum on a specified channel.

thanks thus far for your help pete

  • You must to post comments
0
0

that looks right, except you are playing the sound twice, you only need 1 of those playsound calls.

next you would use FMOD::System::createDSPByType and after playing the sound just use Channel::addDSP, or before playing the sound you could just apply it to the whole mixer output if you want with System::addDSP

  • You must to post comments
0
0

[quote:123pcta8]Address of a variable that receives the spectrum data. This is an array of floating point values. Data will range is 0.0 to 1.0. Decibels = 10.0f * (float)log10(val) * 2.0f; See remarks for what the data represents. [/quote:123pcta8]

[quote:123pcta8]entry_hz = (output_rate / 2) / numvalues[/quote:123pcta8]

so lets say we have

numvalues = 1024
outputrate = 44100

The array has a size of 1024
the first element of the array is
[code:123pcta8]entry_hz = (44100 / 2) / 1024
entry_hz = 21.53 hz[/code:123pcta8]

so spectrumarray[0] is the amplitude (0.0 to 1.0) of the signal at 21.53 hz
spectrumarray[1] 43.06 hz
spectrumarray[2] 64.58 hz

spectrumarray[1023] 22050 Hz

-Pete

  • You must to post comments
0
0

[quote="brett":z78hih09]that looks right, except you are playing the sound twice, you only need 1 of those playsound calls.

next you would use FMOD::System::createDSPByType and after playing the sound just use Channel::addDSP, or before playing the sound you could just apply it to the whole mixer output if you want with System::addDSP[/quote:z78hih09]

thanks for your reply brett. sorry to sound like a complete noob, unfortunately that is what i am! but could you expand on your reply with some code? as mentioned before, i’m looking to add a square wave oscillator dsp effect before the recorded sound is outputted.

  • You must to post comments
0
0

note outputrate is 48000 and spectrumsize is 8192

[code:182n5cgx]
float[] spectrum = new float[SPECTRUMSIZE];
float pos = 0.0f;
ERRCHECK(channel.getSpectrum(spectrum, SPECTRUMSIZE, 0, FMOD.DSP_FFT_WINDOW.TRIANGLE));
ERRCHECK(osc_channel.getSpectrum(osc_spectrum, SPECTRUMSIZE, 0, FMOD.DSP_FFT_WINDOW.TRIANGLE));

            for (int i = 1; i < SPECTRUMSIZE; i++)
            {
                pos = ((OUTPUTRATE / 2) / SPECTRUMSIZE) * i;
                if ((pos > 500.0f)&&(pos < 1000.0f)) {
                    // set amplitude of osc_channel[pos] to that of channel[pos]
                }
            }[/code:182n5cgx]

using your reply, is the correct way i should be implementing the filter bank? (this is just an example 1 band at the moment). i’m getting a crash when i try to do this after i implemented having 2 channels.

I’m going to paste some VERY brief notes was given on ‘how to create a filter bank in FMOD’ by someone, if its of any use:

[quote:182n5cgx]

• First disconnect the channel head from the channel mixer (default input):
DSP dsphead = new DSP();
ErrorCheck(channel.getDSPHead(dsphead));
DSP dspmix = new DSP();
ErrorCheck(result = dsphead.getInput(0, dspmix, null));
ErrorCheck(dsphead.disconnectFrom(dspmix));

• Per band, add a high pass filter, remembering the connection:
dspCon2 = new DSPConnection();
ErrorCheck(dsphead.addInput(hpfilt2, dspCon));
• … and a low pass filter:
ErrorCheck(hpfilt2.addInput(lpfilt2));
• … and connect the low pass to the mixer:
ErrorCheck(lpfilt2.addInput(dspmix));
• Repeat for all bands (1st and last need only 1 filter)

ErrorCheck(dspCon.setMix(0.1));
• You need a loop, that updates the levels every time the voice signal is analysed
while (!system.isNull()){
ErrorCheck(c_control.getSpectrum(spectrum,
SPECTRUMSIZE, 0,FMOD_DSP_FFT_WINDOW_HANNING));
… // adjust filterbank levels
Thread.sleep(10); // be economical with CPU
}[/quote:182n5cgx]

  • You must to post comments
0
0

I think there is some confusion here.
[quote:181ty6w3]i want to apply an effect so that the output from the microphone is modified[/quote:181ty6w3]

Then you want a DSP effect which is not an oscillator. An oscillator is a sound source. It creates sound, I think you want something which will modify the sound like echo, pitchshift, reverb, etc.

To create an instance of a DSP you can use [b:181ty6w3]FMOD::System::createDSPByType[/b:181ty6w3]

To apply that DSP to a channel you can use [b:181ty6w3]FMOD::Channel::addDSP[/b:181ty6w3]

The API reference (fmodex.chm) lists all the FMOD DSP types.

-Pete

  • You must to post comments
0
0

Hi,
it’s my first post on FMOD and i’m new to FMod so don’t by angry for me.
Im trying to make my own low-pass and high-pass filters for learning. And i have a problem to inplement pseudocode from: [url:15o80qb1]http://en.wikipedia.org/wiki/Low-pass_filter[/url:15o80qb1]
There is a formula :
[quote:15o80qb1]
a – alpha
dt – delta t
[/quote:15o80qb1]

[quote:15o80qb1]
a := dt / (RC + dt)
y[i] := a * x[i] + (1-a) * y[i-1]
[/quote:15o80qb1]

My problem :
what is a dt and how to get it on FMOD
Is there another way to do this without RC basing only on frequency to cut off ?
Please help me or give some advices.

best regards
dylek

  • You must to post comments
0
0

ah sorry for being unclear. ultimately, ive been given a task to create a vocoder.

apparently, after taking audio input, i should implement a carrier signal generation using square wave and send that through a dps filter to the audio output. i’m looking at the ‘generatetone’ example for this.

There is more stages in the vocoder such as seperating critical bands and then modifying each bands amplitude.

Am I right by thinking that audio is recorded and then played back but with a square wave filter effect?

  • You must to post comments
0
0

This question is well outside the scope of these forums, but I will answer a couple of questions to get you started.

[quote:3dgqi4nu]what is a dt[/quote:3dgqi4nu]
from the article you linked to:
[quote:3dgqi4nu]time interval dt[/quote:3dgqi4nu]
d is ‘difference’ or ‘delta’ which means the change since the last computation.
t is time.

[quote:3dgqi4nu]how to get it on FMOD[/quote:3dgqi4nu]
Sound plays at X samples per second and you are getting an array of samples being passed to your DSP function. You should be able to work out the time difference using that number of samples (size of array) and the samples per second (output frequency).

You would probably have better luck getting help with this sort of question on a DSP forum. We can help you with questions directly relating to FMOD.

-Pete

  • You must to post comments
0
0

These are the guidelines i have been told to follow to create a vocoder.

  1. Implement a spectrum analysis of live audio input (the ‘control signal’) based on the the “pitchdection”
    example (i.e. strip down the program to just opening the audio input and extracting the spectrum data).

  2. Implement a carrier signal generation using square wave based on the “generatetone” example and send
    that to the audio output. Implement a GUI or command line control that regulates the square wave frequency.

  3. Implement a filter bank that separates all critical bands up to 8kHz using 4 bands per octave above 500
    Hz.

  4. Implement a module that sets the gain of every critical band separated by the filter bank to the value of
    the amplitude in that band in the spectrum of the control signal (task 1), averaging where necessary.

So far, i think i have tasks 1 and 2 done? Although perhaps wrong. I would greatly appriciate any help with tasks 3 and 4.. i’m slightly lost. =P Related code:

[code:1imwat8z]/*
Start recording
*/
result = system.recordStart(selected, sound, true);
ERRCHECK(result);

        Thread.Sleep(200);      /* Give it some time to record something */

        /*
            Play the sound
        */
        ERRCHECK(system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel));

        ERRCHECK(system.createDSPByType(FMOD.DSP_TYPE.OSCILLATOR, ref square_osc));

        ERRCHECK(square_osc.setParameter((int)FMOD.DSP_OSCILLATOR.RATE, 440.0f)); /* musical note 'A' */

        ERRCHECK(square_osc.setParameter((int)FMOD.DSP_OSCILLATOR.TYPE, 1));

        ERRCHECK(system.playDSP(FMOD.CHANNELINDEX.REUSE, square_osc, true, ref channel));
        channel.setPaused(false);

        /*
         Create the DSP effects.
        */
        ERRCHECK(system.createDSPByType(FMOD.DSP_TYPE.LOWPASS, ref dsplowpass));
        ERRCHECK(system.createDSPByType(FMOD.DSP_TYPE.HIGHPASS, ref dsphighpass));

        ERRCHECK(system.getDSPHead(ref dsphead));

        ERRCHECK(dsphead.getInput(0, ref dspchannelmixer, ref dspconnectiontemp));

        ERRCHECK(dsphead.disconnectFrom(dspchannelmixer));

        ERRCHECK(dsphead.addInput(dsplowpass, ref dsplowpassconnection));

        ERRCHECK(dsphead.addInput(dsphighpass, ref dsphighpassconnection));

        ERRCHECK(dsplowpass.addInput(dspchannelmixer, ref dspconnectiontemp));

        ERRCHECK(dsphighpass.addInput(dspchannelmixer, ref dspconnectiontemp));

        //dsplowpass.setBypass(true);
        //dsphighpass.setBypass(true);
        ERRCHECK(dsplowpass.setActive(true));
        ERRCHECK(dsphighpass.setActive(true));

        /* Dont hear what is being recorded otherwise it will feedback.  Spectrum analysis is done before volume scaling in the DSP chain */
        ERRCHECK(channel.setVolume(0.01f));[/code:1imwat8z]
  • You must to post comments
0
0

Hi,
thaks for reply, i’ve done what I want to do, but there is another problem.
All what i want to do is:
– play some WAVE (done)
– put o it some DSP (done)
– write this changed by DSP to another WAVE file. (probelm)
Is there some way to do this ??

I want make huffman compresion, so i need all samples in a table. Meke on it some modyfikation and save to file.

  • You must to post comments
0
0

[quote:3usz9z97]So far, i think i have tasks 1 and 2 done?[/quote:3usz9z97]
You have done task 2. I don’t see any code from the pitchdetection example so you haven’t done that one. The glaring omission being the usage of the Channel::getspectrum function.

You seem to be using ERRCHECK on some functions and not others, if this is intentional (i.e those function were returning pesky error messages) those errors should be handled not ignored.

You don’t need the highpass and lowpass filters.

Your creation of the oscillator looks correct and the recording code looks good too. Next I think you should spend some time reading the code for our pitchdetection example.

-Pete

  • You must to post comments
0
0

To write out a wave file you can use the output mode to FMOD_OUTPUTTYPE_WAVWRITER which will write all the data to an uncompressed wav file. Alternatively you can get access to the raw data by creating another DSP unit and attaching it to the master channel group. If you want any kind of compression you will have to do that your self, FMOD doesn’t compress the output file.

-Pete

  • You must to post comments
0
0

Hey, thanks for the reply. I didn’t include the get spectrum part yet as i felt it had no use for it until i implement the filter bank, but now i’ve put it in under playing the sound. Another part of the program (selecting input/output drivers) and also the recording code is taken from the pitchdetection example.

The highpass/lowpass filters i forgot to ommit, i was just practicing with to ensure they were working. But i need them to split the carrier into frequency bands, right?

How would i go about task 3? I’m not sure exactly how to ‘implement’ a filter bank.. i assume i’ll need to add a high pass & low pass filter per band but not sure how to get the code in place for this task. Any help MUCH appriciated.

[code:275mhmtw] /*
Start recording
*/
ERRCHECK(system.recordStart(selected, sound, true));

        Thread.Sleep(200);      /* Give it some time to record something */

        /*
            Play the sound
        */
        ERRCHECK(system.playSound(FMOD.CHANNELINDEX.FREE, sound, false, ref channel));

        ERRCHECK(channel.getSpectrum(spectrum, SPECTRUMSIZE, 0, FMOD.DSP_FFT_WINDOW.TRIANGLE));

        ERRCHECK(system.createDSPByType(FMOD.DSP_TYPE.OSCILLATOR, ref square_osc));

        ERRCHECK(square_osc.setParameter((int)FMOD.DSP_OSCILLATOR.RATE, 440.0f)); /* musical note 'A' */

        ERRCHECK(square_osc.setParameter((int)FMOD.DSP_OSCILLATOR.TYPE, 1));

        ERRCHECK(system.playDSP(FMOD.CHANNELINDEX.REUSE, square_osc, true, ref channel));
        ERRCHECK(channel.setPaused(false));

        /*
         Create the DSP effects.
        */
        ERRCHECK(system.createDSPByType(FMOD.DSP_TYPE.LOWPASS, ref dsplowpass));
        ERRCHECK(system.createDSPByType(FMOD.DSP_TYPE.HIGHPASS, ref dsphighpass));

        ERRCHECK(system.getDSPHead(ref dsphead));

        ERRCHECK(dsphead.getInput(0, ref dspchannelmixer, ref dspconnectiontemp));

        ERRCHECK(dsphead.disconnectFrom(dspchannelmixer));

        ERRCHECK(dsphead.addInput(dsplowpass, ref dsplowpassconnection));

        ERRCHECK(dsphead.addInput(dsphighpass, ref dsphighpassconnection));

        ERRCHECK(dsplowpass.addInput(dspchannelmixer, ref dspconnectiontemp));

        ERRCHECK(dsphighpass.addInput(dspchannelmixer, ref dspconnectiontemp));

        //dsplowpass.setBypass(true);
        //dsphighpass.setBypass(true);
        ERRCHECK(dsplowpass.setActive(true));
        ERRCHECK(dsphighpass.setActive(true));

        /* Dont hear what is being recorded otherwise it will feedback.  Spectrum analysis is done before volume scaling in the DSP chain */
        ERRCHECK(channel.setVolume(0.01f));[/code:275mhmtw]
  • You must to post comments
0
0

[quote="PeterStirling":27dbqpe1]If you want any kind of compression you will have to do that your self, FMOD doesn’t compress the output file.[/quote:27dbqpe1]

I understand this.
Maybe i explain in another way:
– I am taking all samples by DSP callback
– I am modify them by my compress function.
– I am saving them to binnary file with neded datas like channels, bits, rate
and all is ok to the moment when i want to decode it and save to wave ar play.
– I am reading this binnary file and decoding it so i have all samples and info about channels, bits, and rate.
– problem is here how put all this data to wav file and/or play them ?

  • You must to post comments
0
0

I think you’ll find the getSpectrum function does all that work for you. This is what the docs say for that function:
[code:2arvu99j]
FMOD_RESULT Channel::getSpectrum( float *spectrumarray, int numvalues, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype );[/code:2arvu99j]

spectrumarray

Address of a variable that receives the spectrum data. This is an array of floating point values. Data will range is 0.0 to 1.0. Decibels = 10.0f * (float)log10(val) * 2.0f; See remarks for what the data represents.

[u:2arvu99j]
What the data represents.[/u:2arvu99j]
To work out what each entry in the array represents, use this formula

[code:2arvu99j]
entry_hz = (output_rate / 2) / numvalues[/code:2arvu99j]

The array represents amplitudes of each frequency band from 0hz to the nyquist rate. The nyquist rate is equal to the output rate divided by 2.
For example when FMOD is set to 44100hz output, the range of represented frequencies will be 0hz to 22049hz, a total of 22050hz represented.
If in the same example, 1024 was passed to this function as the numvalues, each entry’s contribution would be as follows.
[code:2arvu99j]entry_hz = (44100 / 2) / 1024
entry_hz = 21.53 hz[/code:2arvu99j]

-Pete

  • You must to post comments
0
0

To play raw uncompressed data you have stored in memory you can use System::createSound with mode = FMOD_OPENRAW | FMOD_OPENMEMORY_POINT

This requires defaultfrequency, numchannels and format to be specified in a FMOD_CREATESOUNDEXINFO struct. It must be little endian data.

-Pete

  • You must to post comments
0
0

hi, appriciate your reply but i’ll have to be honest and say that i dont understand how the getspectrum function can implement a filter bank for me.

[quote:3mfg6e11]3. Implement a filter bank that separates all critical bands up to 8kHz using 4 bands per octave above 500Hz.

  1. Implement a module that sets the gain of every critical band separated by the filter bank to the value of the amplitude in that band in the spectrum of the control signal (task 1), averaging where necessary. [/quote:3mfg6e11]

i’m getting very stuck and very frustrated. my knowledge of audio processing is very limited and this is proving a challenging task, but still its nescessary that i complete it. ;(

  • You must to post comments
0
0

Again me 😉

in the usercreatedsound sample i found:
[code:2tpnmej8]
FMOD_RESULT F_CALLBACK pcmreadcallback(FMOD_SOUND *sound, void *data, unsigned int datalen)
{
unsigned int count;
static float t1 = 0, t2 = 0; // time
static float v1 = 0, v2 = 0; // velocity
signed short *stereo16bitbuffer = (signed short *)data;

for (count=0; count<datalen>>2; count++)        // >>2 = 16bit stereo (4 bytes per sample)
{
    *stereo16bitbuffer++ = (signed short)(sin(t1) * 32767.0f);    // left channel

    *stereo16bitbuffer++ = (signed short)(sin(t2) * 32767.0f);    // right channel

    t1 += 0.01f   + v1;
    t2 += 0.0142f + v2;
    v1 += (float)(sin(t1) * 0.002f);
    v2 += (float)(sin(t2) * 0.002f);
}

return FMOD_OK;

}[/code:2tpnmej8]

What kind of data type it is :
[code:2tpnmej8]void *data[/code:2tpnmej8]
It is the same what i get by
[code:2tpnmej8]sound->readData((char *)data, CHUNKSIZE, &read);[/code:2tpnmej8]
or
[code:2tpnmej8]float *inbuffer[/code:2tpnmej8]
from DSP callback function ?

And the last question the most important for me:
Is it possible to translate data which i get by
[code:2tpnmej8]Sound::lock()[/code:2tpnmej8]
i mean [void ** ptr1] sample by sample on a frequency or on data type like e.g. float ?

  • You must to post comments
Showing 1 - 20 of 21 results
Your Answer

Please first to submit.