Urgent - Record a file in 16KHz or downsampling a file to 16KHz

The problem is that I need to record a file in 16KHz, but I found JUCE does not support 16KHz sample rate. Therefore I have to record it in 44.1KHz and resample it to 16KHz.

  1. Is there a way to record a file in 16KHz?
  2. If no for Qn 1, how can I resample it to 16KHz?

I found the class ResamplingAudioSource class but don't know how to use it. Is the class to paly a file at a new sample rate (say 16KHz) or to get a new file with the new sample rate (say 16KHz) ? I need the latter, since I need to use AudioFormatReader::read function to get the raw data in 2d array (int**).

I am new to JUCE and I need to solve the problem as soon as possible. Hope someone can give me some help.

Thanks.

If you just want to resample the file offline your best bet is to probably just run it through the LagrangeInterpolator (http://www.juce.com/api/classLagrangeInterpolator.html).

Function --- process (double speedRatio, const float *inputSamples, float *outputSamples, int numOutputSamplesToProduce)

So if I want to resample from 44.1KHz to 16KHz, the speedRatio should be (44.1 / 16), is it?

And the input/output samples are in float, are they in the range of -1.0 to 1.0?

Really thank you!!

The speed ratio parameter is explained in the docs, and yes, floating point audio samples are always -1 to 1!

So what would be the problem if it works for resampling a 16K to 16K, while it fails for resampling 44.1K to 16K?

I think I have set the speedRation correctly to be (actual_sample_rate/16000).

Otherwise, is there a way to record 16KHz audio. That will be easier.

Without showing your code, or even saying how it fails, I think you're being optimistic if you expect anyone to help you with that.

ResamplingAudioSource?

Get a good app like SoundForge

Code is as bellow. Basically it compares two singing files and gives scores for the user.

 

    ScopedPointer<File> proFile = new File("E129_Sing_L_003.wav"); // professional singing

    ScopedPointer<File> userFile = new File("E129_Sing_L_003_user_0.wav"); // user singing

 

    int ** proData;

    int *rows = new int;

    int *cols = new int;

    readRawData(proFile, &proData, rows, cols); // read all channels data

    emxArray_real32_T * proArr; //This is a structure of matlab matrix

    proArr = emxCreateWrapper_real32_T(getLeftChanData(proData, *cols), *cols, 1); 

 

    int ** userData;

    int *userrows = new int;

    int *usercols = new int;

    readRawData(userFile, &userData, userrows, usercols);

    float speedRation = (float)userReader->sampleRate / 16000;

    int numOutputSamples = (int) floorf((float)*usercols / speedRation);

    float *outputSamples = new float[numOutputSamples];

    resampling.process(speedRation, getLeftChanData(userData, *usercols), outputSamples, numOutputSamples);

    emxArray_real32_T * userArr;

    userArr = emxCreateWrapper_real32_T(outputSamples, numOutputSamples, 1);

 

    timingScore = new float;

    pitchScore = new float;

    status = new int;

    wrongTimingMarks = emxCreate_real32_T(*rows, *cols);

    wrongPitchMarks = emxCreate_real32_T(*rows, *cols);

    EvaluateSinging(userArr, proArr, timingScore, wrongTimingMarks, pitchScore, wrongPitchMarks, status); 

 

EvaluateSinging function is converted from matlab code so very difficult to read. professional singing is always 16K. When user singing is 16K, I get the correct score. When user singing is 44.1K, the program got stuck somewhere withn the EvaluateSinging function, showing EXC_BAD_ACCESS.

    

If you dont care that much about quality, you can try this i quickly threw together (not tested though):


template <typename f>
size_t resample(f ** in, size_t numInSamples, f ** out, size_t numOutSamples, size_t numChannels, float factor)
{
    size_t sample = 0;
    while (numInSamples > 0 && numOutSamples > 0)
    {
        for (size_t channel = 0; channel < numChannels; ++channel)
        {
            float index = sample * factor;
            size_t x1 = static_cast<size_t>(index); // floor
            size_t x2 = x1 + 1; // ceil
            float mu = index - x1; // remainder
            out[channel][sample] = (in[channel][x1] * (1 - mu) + in[channel][x2] * mu);
        }
        ++sample, --numInSamples, --numOutSamples;
    }
    return sample;
}

It will resample using linear interpolation. Usage:

auto numSamples = resample(buf44100float, num44100Samples, buf16000float, num16000Samples, 2, 44100.0 / 16000.0);

eh, I cannot do it using other apps. I must implement it in my software using JUCE.

How to use ResamplingAudioSource to record a audio file? I am currently doing recording the same way as the JUCEDemo.

Thanks

There's nothing wrong with the LagrangeInterpolator, we use it all the time in Tracktion.

Have you dumped your re-sampled audio to a file to hear what it sounds like?

There's a hell of a lot of problems with that code you posted, any number of things could be causing it to crash. You should learn the basics of RAII. Here's a couple of places to start:

- Why are you creating a File on the heap? They're lightweight wrappers around a String, just put it on the stack.

- Where is userData pointing to?

- userrows and usercols are just single ints on the heap? Why?

- You don't show if you actually delete any of the huge amount of things you create on the heap. Use proper containers such as an AudioSampleBuffer or even HeapBlock.

 

It feels like you're just creating pointers to things to fit in with an API rather than understanding what they do. I think that whole function needs re-writing so it's clearer and safer.

Thanks for your suggestions.

This is my school project. I don't know much about audio actually. Someone already developed the algorithms for comparing audio data. I just need to get the left channel singing data (in float*) and pass to the EvaluateSinging function and show the pitchScore and timgScore.

userData points to the 2d int array of singing data, userrows and usercols points to single integer. All because I need pass by pointer, they are actually the results I want to get from the readRawData.

I don't know much about heap and stack also. I know how to use them as data sturcture, but basically that's all.

Oh yes, AudioSampleBuffer is easy to handle. but how to combine it with ResamplingAudioSource? some example code?

Sorry, but I am new to JUCE and I am not a good C++ programmer also. Can you explain in more details? Basically now I just want to know how to do resampling, pass the data to evaluateSinging fucntion and get correct result, because tomorrow is the deadline.

Thank you.

Sorry but what's the difference between sample and numOutSamples?

 

Sorry what is the difference between numOutSamples and sample? Do they mean different thing?

sample will be the amount of samples copied into the output buffer. This can be at max the same amount as numOutSamples, however it can be smaller if the inputbuffer is of significant less size.