# Recording Issue

**URL:** <https://forum.juce.com/t/recording-issue/32383>\
**Category:** General JUCE discussion\
**Created:** [March 20, 2019, 10:22am UTC](https://forum.juce.com/t/recording-issue/32383 "2019-03-20T10:22:34Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![gcass002](https://avatars.discourse-cdn.com/v4/letter/g/779978/32.png) [@gcass002](https://forum.juce.com/u/gcass002)\
**Post date:** [March 20, 2019, 10:22am UTC](https://forum.juce.com/t/recording-issue/32383/1 "2019-03-20T10:22:35Z")

</div>

I i am trying to record this way

```
void AudioRecorder::startRecording (AudioBuffer<float>* bufferToRecord, const File& file)
{
    stop();
    
    // file.deleteFile();
    
    //get numChannel based on the track need (Mono or Stereo)
    auto numChannels = bufferToRecord->getNumChannels();
    
    
    //create a new file based on the passed argument
    
    writer.reset (format.createWriterFor (new FileOutputStream (file),
                                          44100.0,
                                          numChannels,
                                          24,
                                          {},
                                          0));
}

//=============================================================================
//Actual Recording

void AudioRecorder::Record(AudioBuffer<float>* bufferToRecord)
{
    const auto numSamples = bufferToRecord->getNumSamples();
    if (writer != 0)
    {
        writer->writeFromAudioSampleBuffer(*bufferToRecord, 0, numSamples);
    }
}

```

and it actually create and write on a .wav, except for the fact that the .wav output is slowed down and distorted  
Anyone encountered this problem ?

Fun fact : I am flying to Berlin and I am on the same plane with Jean-Baptiste Thiebaut

---

<div class="post-metadata">

**Author:** ![gcass002](https://avatars.discourse-cdn.com/v4/letter/g/779978/32.png) [@gcass002](https://forum.juce.com/u/gcass002)\
**Post date:** [March 20, 2019, 10:29am UTC](https://forum.juce.com/t/recording-issue/32383/2 "2019-03-20T10:29:54Z")

</div>

I am not using any background Thread… all of this is called on the getNextAudioBlock() of one of my audioSources and i am using

std::unique\_ptr writer, not

std::atomic\<;AudioFormatWriter::ThreadedWriter\*\> activeWriter ;

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [March 20, 2019, 1:12pm UTC](https://forum.juce.com/t/recording-issue/32383/3 "2019-03-20T13:12:06Z")

</div>

You set the writer to write 44100 Hz into the header, but you don’t check, if your audio device is actually running at that speed. It seems rather to run on 48000 Hz judging by your description.

N.B. say hi to JB 🙂 (well 3 hrs, you are probably there by now…)

---

<div class="post-metadata">

**Author:** ![gcass002](https://avatars.discourse-cdn.com/v4/letter/g/779978/32.png) [@gcass002](https://forum.juce.com/u/gcass002)\
**Post date:** [March 20, 2019, 7:04pm UTC](https://forum.juce.com/t/recording-issue/32383/4 "2019-03-20T19:04:56Z")

</div>

> [@daniel](#):
>
> running at that s

I can confirm my device is working at 44100.

I mess a bit around and I noticed **two** things :

**1**. if i divide the num of samples by two  
writer-\>writeFromAudioSampleBuffer(\*bufferToRecord, 0, _ **numSamples/2** _);  
the beat does not slow down…

**2**. If i change the buffer size of the DeviceManager from the AudioDeviceSelector **from 512 to 16 samples the distortion almost goes away** …

would you know what could be the problems that brought to this two behaviours ?

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [March 20, 2019, 7:11pm UTC](https://forum.juce.com/t/recording-issue/32383/5 "2019-03-20T19:11:31Z")

</div>

Can you show the code, where your AudioRecorder::Record method is called? I would be interested, how you fill the buffer.  
If it is slowed down, that sounds like you are sending more samples, than you are actually having available, hence the written signal becomes longer. And since the additional samples from each block are not part of the signal, that might be the distortion you are hearing.

---

<div class="post-metadata">

**Author:** ![gcass002](https://avatars.discourse-cdn.com/v4/letter/g/779978/32.png) [@gcass002](https://forum.juce.com/u/gcass002)\
**Post date:** [March 21, 2019, 11:46am UTC](https://forum.juce.com/t/recording-issue/32383/6 "2019-03-21T11:46:35Z")

</div>

```
void Track::prepareToPlay (int samplesPerBlockExpected, double sampleRate) {

    bufferToRecordL.setSize(1, samplesPerBlockExpected);
    bufferToRecordR.setSize(1, samplesPerBlockExpected);
    bufferToRecordStereo.setSize(2, samplesPerBlockExpected);

        
}
void Track::releaseResources() {}

void Track::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) {
    
    if (inputL){
    
        if(!isStereo){
            
        //copy the desired content(channel) from bufferToFill and pass it to the recorder
    const auto numSamples = bufferToFill.buffer->getNumSamples();
          
            bufferToRecordL.copyFrom(0, 0, *bufferToFill.buffer, (inputL - 1), 0, numSamples);
        
           
            bufferToFill.clearActiveBufferRegion();
            
            bufferToRecordL.applyGain(0, 0, numSamples, sliderValue);
            
            if (recordState == RecordState::Recording)
                **recorder.Record(&bufferToRecordL);**
          
            bufferToFill.buffer->addFrom(0, 0, bufferToRecordL, 0, 0, numSamples);
            bufferToFill.buffer->addFrom(1, 0, bufferToRecordL, 0, 0, numSamples);
    
        
            
    }
        if(isStereo){
       
            //copy the desired content(channel) from bufferToFill and pass it to the recorder
            const auto numSamples = bufferToFill.buffer->getNumSamples();
            bufferToRecordL.copyFrom(0, 0, *bufferToFill.buffer, (inputL - 1), 0, numSamples);
            bufferToRecordR.copyFrom(0, 0, *bufferToFill.buffer, (inputR - 1), 0, numSamples);

            bufferToFill.clearActiveBufferRegion();

            bufferToRecordStereo.copyFrom(0, 0, bufferToRecordL, 0, 0, numSamples);
            bufferToRecordStereo.copyFrom(1, 0, bufferToRecordR, 0, 0, numSamples);
            
            bufferToRecordStereo.applyGain(0, 0, numSamples, sliderValue);
            bufferToRecordStereo.applyGain(1, 0, numSamples, sliderValue);
  
            if (recordState == RecordState::Recording)
                recorder.Record(&bufferToRecordStereo);
            
            bufferToFill.buffer->addFrom(0, 0, bufferToRecordStereo, 0, 0, numSamples);
            bufferToFill.buffer->addFrom(1, 0, bufferToRecordStereo, 1, 0, numSamples);
            
            
        };
    }
    
     else {
         
         bufferToFill.clearActiveBufferRegion();}
}
```

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [March 21, 2019, 12:00pm UTC](https://forum.juce.com/t/recording-issue/32383/7 "2019-03-21T12:00:25Z")

</div>

The problem seems to me, that you are using the buffer from the AudioSourceChannelInfo.buffer.  
Instead you should only copy info.numSamples starting at info.startSample.

I would suggest to change the signature of your Record method to:

```
void AudioRecorder::Record (const AudioBuffer<float>& bufferToRecord)

```

and call it like:

```auto
void Track::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
    if (recordState == RecordState::Recording)
    {
        AudioBuffer<float> proxy (bufferToFill.buffer->getArrayOfWritePointers(),
                                  bufferToFill.buffer->getNumChannels(),
                                  bufferToFill.startSample,
                                  bufferToFill.numSamples);
        recorder.Record (proxy);
    }
    // ...
}

```

Aslo moving forward, remember you are writing to a potentially slow disk in the audio thread, so have a look at [ThreadedWriter](https://docs.juce.com/develop/classAudioFormatWriter_1_1ThreadedWriter.html)

Hope that helps

---

<div class="post-metadata">

**Author:** ![gcass002](https://avatars.discourse-cdn.com/v4/letter/g/779978/32.png) [@gcass002](https://forum.juce.com/u/gcass002)\
**Post date:** [March 21, 2019, 12:38pm UTC](https://forum.juce.com/t/recording-issue/32383/8 "2019-03-21T12:38:19Z")

</div>

Thanks a lot for your time  
I am going to work at it later and let you know…

Just one thing, so your suggestion is to pass the entire bufferToFil(proxy) to the recorder and then do the copyFrom and stuff into the recorder ?

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [March 21, 2019, 2:19pm UTC](https://forum.juce.com/t/recording-issue/32383/9 "2019-03-21T14:19:18Z")

</div>

Since your Recorder code is used to write the whole buffer, but the AudioSourceChannelInfo is designed to denote a subset of that buffer, I suggest to create this proxy buffer.  
It references the audio data coming in from AudioSourceChannelInfo, but looks like it is starting at startSample and is numSamples long.

There is no need to copy stuff around, it will wait until it is written anyway (which is the problem, that you can avoid with ThreadedWriter. That will copy the needed data and return immediately)

---

<div class="post-metadata">

**Author:** ![gcass002](https://avatars.discourse-cdn.com/v4/letter/g/779978/32.png) [@gcass002](https://forum.juce.com/u/gcass002)\
**Post date:** [March 22, 2019, 10:57am UTC](https://forum.juce.com/t/recording-issue/32383/11 "2019-03-22T10:57:48Z")

</div>

[1m](https://forum.juce.com/t/recording-issue/32383/10?u=gcass002)

Maybe I am using the wrong approach, but i need the copyFrom because i am using it to send to Record only the channels I desire.

How would you select only a pair or a single channel to send ?

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [March 22, 2019, 11:05am UTC](https://forum.juce.com/t/recording-issue/32383/12 "2019-03-22T11:05:06Z")

</div>

You can supply your own array of write pointers:

```auto
void Track::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
    if (recordState == RecordState::Recording)
    {
        float* pointers [2] = { bufferToFill.buffer->getWritePointer (1), 
                                bufferToFill.buffer->getWritePointer (3) };
        AudioBuffer<float> proxy (pointers, 2, bufferToFill.startSample, bufferToFill.numSamples);
        recorder.Record (proxy);
    }
    // ...
}

```

I think you can even assign the same pointer twice to turn a mono into stereo…

---

<div class="post-metadata">

**Author:** ![gcass002](https://avatars.discourse-cdn.com/v4/letter/g/779978/32.png) [@gcass002](https://forum.juce.com/u/gcass002)\
**Post date:** [March 23, 2019, 9:43am UTC](https://forum.juce.com/t/recording-issue/32383/14 "2019-03-23T09:43:15Z")

</div>

In order to implement the ThreadedWriter I have looked at the Demo code and I can see it uses a AudioIODeviceCallback therefore it has const float\*\* inputChannelData to -\>write,  
Instead I am doing my recording in the getNextAudioBlock() from my AudioSources…  
Is there a way to convert BufferToFill into const float\*\* inputChannelData ?  
cause the ThreadedWriter doesn’t seem to have accept the function writeFromSampleBuffer …

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [March 23, 2019, 11:13am UTC](https://forum.juce.com/t/recording-issue/32383/15 "2019-03-23T11:13:57Z")

</div>

The method to get a `float**` from a `AudioBuffer<float>` is `buffer.getArrayOfWritePointers()`.  
But in your case that makes things even easier, you take the startSample into account when you create the pointer array (`float* pointers[2]` is the same like `float** pointers`, simplified speaking).  
So you can scrap the proxy buffer and call:

```auto
float* pointers [2] = { bufferToFill.buffer->getWritePointer (1, bufferToFill.startSample), 
                        bufferToFill.buffer->getWritePointer (3, bufferToFill.startSample) };
threadedWriter.write (pointers, bufferToFill.numSamples);

```

It is probably the easiest way to change your record method to look like:

```auto
void AudioRecorder::Record (const AudioSourceChannelInfo& bufferToFill)

```

that way you can keep the needed information together, and the recorder can then decide, which channel to record etc.

---

<div class="post-metadata">

**Author:** ![gcass002](https://avatars.discourse-cdn.com/v4/letter/g/779978/32.png) [@gcass002](https://forum.juce.com/u/gcass002)\
**Post date:** [March 23, 2019, 4:38pm UTC](https://forum.juce.com/t/recording-issue/32383/16 "2019-03-23T16:38:52Z")

</div>

Daniel… I can’t believe I finally got it… the problem was that i was setting the track as as source for two AudioSourcePlayer  
this was residue of my old implementation :

`// audioSourcePlayer.setSource(fTracks.getLast()); in the mainComponent.cpp`

and this was the actual implementation :

```
Track* newTrack = new Track("Track",
                             &sliderTrack1,
                             &buttonTrack1,
                             "2",
                             &midiCollector,
                             newTree,
                             undoManager);
    
    fTracks.add (newTrack);
    tracks.items.add(FlexItem(200, 200, *fTracks.getLast()));
    
    AudioSourcePlayer* newAudioSourcePlayer = new AudioSourcePlayer;
    audioSourcePlayers.add(newAudioSourcePlayer);
    audioSourcePlayers.getLast()->setSource(fTracks.getLast());
    deviceManager.addAudioCallback(audioSourcePlayers.getLast());

```

The two were colliding… remove the first and everything was fine 🤣

Thanks so much for the suggestion about the new implementation with pointers and the getArrayOfWritePointers function was really illuminating as a newbie in JUCE…

I feel stupid and sorry for making you waste your time but in the end now I have ThreadedWriter record function that is very cool !!!

---

<div class="post-metadata">

**Author:** ![daniel](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/daniel/32/790_2.png) [@daniel](https://forum.juce.com/u/daniel)\
**Post date:** [March 23, 2019, 4:57pm UTC](https://forum.juce.com/t/recording-issue/32383/17 "2019-03-23T16:57:00Z")

</div>

Lovely, glad it all works out 🙂
