Multiple audio recording and playback (urgent help needed)

I am trying to have three recording inputs and playbacks…

Here is my code that I am trying…
Can someone help me?

my “testApp.h” file:
#pragma once

#include “ofMain.h”
#include “ofxiOS.h”
#include “ofxiOSExtras.h”
#include “padButton.h”

class testApp : public ofxiOSApp{

public:
    void setup();
    void update();
    void draw();
    void exit();

    void touchDown(ofTouchEventArgs & touch);
    void touchMoved(ofTouchEventArgs & touch);
    void touchUp(ofTouchEventArgs & touch);
    void touchDoubleTap(ofTouchEventArgs & touch);
    void touchCancelled(ofTouchEventArgs & touch);

    void lostFocus();
    void gotFocus();
    void gotMemoryWarning();
    void deviceOrientationChanged(int newOrientation);

void audioIn( float * input, int bufferSize, int nChannels );
void audioOut( float * output, int bufferSize, int nChannels );


// our screen size
int                 width, height;

// variable for audio
int                 initialBufferSize;
int                 sampleRate;

// this vector will store our audio recording
vector<float>       buffer01, buffer02;


// frame will tell us "what chunk of audio are we currently playing back".
// as we record and play back in "chunks" also called "frames", we will need
// to keep track of which frame we are playing during playback
int                 frame, frame02;

// frame will run until it hits the final recorded frame, which is numFrames
// we increment this value every time we record a new frame of audio
int                 numFrames, numFrames02;

// our buttons for user interaction
padButton           button_play, button_record, button_play02, button_record02;

// determined based on whether the user has pressed the play or record buttons
bool                bRecording, bPlaying, bRecording02, bPlaying02;

};

and here is my “testApp.mm” file:

#include “testApp.h”

//--------------------------------------------------------------
void testApp::setup(){

// register touch events
ofRegisterTouchEvents(this);

ofSetOrientation(OF_ORIENTATION_90_RIGHT);



//for some reason on the iphone simulator 256 doesn't work - it comes in as 512!
//so we do 512 - otherwise we crash
initialBufferSize   = 512;
sampleRate          = 44100;
    
//buffer                = new float[initialBufferSize];
//memset(buffer, 0, initialBufferSize * sizeof(float));

// 1 output channels, <-- different from the previous example, as now we want to playback
// 1 input channels
// 44100 samples per second
// 512 samples per buffer
// 4 num buffers (latency)
ofSoundStreamSetup(1, 1, this, sampleRate, initialBufferSize, 4);
ofSetFrameRate(60);

// we initialize our two buttons to act as a play and a record button.
button_record.loadImages("rec.png", "rec.png");
button_play.loadImages("play.png", "play.png");
button_record.setPosition(100, 100);
button_record.setSize(100, 100);
button_play.setPosition(250, 100);
button_play.setSize(100, 100);

button_record02.loadImages("rec.png", "rec.png");
button_play02.loadImages("play.png", "play.png");
button_record02.setPosition(100, 200);
button_record02.setSize(100, 100);
button_play02.setPosition(250, 200);
button_play02.setSize(100, 100);



// initially not recording
bRecording = false;
bPlaying = false;

// which audio frame am i currently playing back
frame = 0;
frame02 = 0;

// how many audio frames did we record?
numFrames = 0;
numFrames02 = 0;


width = 480;
height = 320;
ofSetWindowShape(width, height);

}

//--------------------------------------------------------------
void testApp::update(){

}

//--------------------------------------------------------------
void testApp::draw(){

ofBackground(0);

// draw our buttons
button_record.draw();
button_play.draw();
button_record02.draw();
button_play02.draw();

ofTranslate(0, height/2);

// let's output a string on the screen that helps us determine what the state of the program is
if (bPlaying) {
    ofDrawBitmapString("Playing: True", 20,20);
}
else {
    ofDrawBitmapString("Playing: False", 20,20);
}

if (bRecording) {
    ofDrawBitmapString("Recording: True", 20,40);
}
else {
    ofDrawBitmapString("Recording: False", 20,40);
}




//second rec and play buttons

if (bPlaying02) {
    ofDrawBitmapString("Recording: True", 20,60);
}
else {
    ofDrawBitmapString("Recording: False", 20,60);
}

if (bRecording02) {
    ofDrawBitmapString("Recording: True", 20,80);
}
else {
    ofDrawBitmapString("Recording: False", 20,80);
}

}

//--------------------------------------------------------------
void testApp::audioOut(float * output, int bufferSize, int nChannels){

// if we are playing back audio (if the user is pressing the play button)
if(bPlaying)
{
    // we set the output to be our recorded buffer
    for (int i = 0; i < bufferSize; i++){
        // so we have to access the current "playback frame" which is a variable
        // "frame".  this variable helps us determine which frame we should play back.
        // because one frame is only 512 samples, or 1/90th of a second of audio, we would like
        // to hear more than just that one frame.  so we playback not just the first frame,
        // but every frame after that... after 90 frames of audio, we will have heard
        // 1 second of the recording...
        output[i] = buffer01[i + frame*bufferSize];
    }
    
    // we have to increase our frame counter in order to hear farther into the audio recording
    frame = (frame + 1) % numFrames;
}
// else don't output anything to the speaker
else {
    memset(output, 0, nChannels * bufferSize * sizeof(float));
}

//second audio out

if(bPlaying02)
{
    for (int i = 0; i < bufferSize; i++){
        output[i] = buffer02[i + frame*bufferSize];
    }
    
    frame = (frame + 1) % numFrames;
}
else {
    memset(output, 0, nChannels * bufferSize * sizeof(float));
}

}

//--------------------------------------------------------------
void testApp::audioIn(float * input, int bufferSize, int nChannels){

if( initialBufferSize != bufferSize ){
    ofLog(OF_LOG_ERROR, "your buffer size was set to %i - but the stream needs a buffer size of %i", initialBufferSize, bufferSize);
    return;
}

// if we are recording
if(bRecording)
{
    // let's add the current frame of audio input to our recording buffer.  this is 512 samples.
    // (note: another way to do this is to copy the whole chunk of memory using memcpy)
    for (int i = 0; i < bufferSize; i++){
        // we will add a sample at a time to the back of the buffer, increasing the size of "buffer"
        buffer01.push_back(input[i]);
    }
    
    // we also need to keep track of how many audio "frames" we have.  this is how many times
    // we have recorded a chunk of 512 samples.  we refer to that chunk of 512 samples as 1 frame.
    numFrames++;
}
// otherwise we set the input to 0
else
{
    // set the chunk in memory pointed to by "input" to 0.  the
    // size of the chunk is the 3rd argument.
    memset(input, 0, nChannels * bufferSize * sizeof(float));
}


//second audio in

if(bRecording02)
{
    for (int i = 0; i < bufferSize; i++){
        buffer02.push_back(input[i]);
    }
    
    numFrames++;
}
else
{
    memset(input, 0, nChannels * bufferSize * sizeof(float));
}

}

//--------------------------------------------------------------

void testApp::exit(){

}

//--------------------------------------------------------------
void testApp::touchDown(ofTouchEventArgs & touch){

//bRecording = !bRecording;

// NOTE: we have modified our button class to return true or false when the button was pressed
// we set playing or recording to be true depending on whether the user pressed that button
bPlaying = button_play.pressed(touch.x, touch.y);
bRecording = button_record.pressed(touch.x, touch.y);
bPlaying02 = button_play02.pressed(touch.x, touch.y);
bRecording02 = button_record02.pressed(touch.x, touch.y);

}

//--------------------------------------------------------------
void testApp::touchMoved(ofTouchEventArgs & touch){

}

//--------------------------------------------------------------
void testApp::touchUp(ofTouchEventArgs & touch){

// we then user stops pressing the button, we are no longer playing or recording
bPlaying = !button_play.released(touch.x, touch.y);
bRecording = !button_record.released(touch.x, touch.y);
bPlaying02 = !button_play02.released(touch.x, touch.y);
bRecording02 = !button_record02.released(touch.x, touch.y);

}

//--------------------------------------------------------------
void testApp::touchDoubleTap(ofTouchEventArgs & touch){

}

//--------------------------------------------------------------
void testApp::touchCancelled(ofTouchEventArgs & touch){

}

//--------------------------------------------------------------
void testApp::lostFocus(){

}

//--------------------------------------------------------------
void testApp::gotFocus(){

}

//--------------------------------------------------------------
void testApp::gotMemoryWarning(){

}

//--------------------------------------------------------------
void testApp::deviceOrientationChanged(int newOrientation){

}

Hi there, what are you trying to do with it?
Have 3 buffers to record into (not simultaneously) and then be able to play them back in polyphony?

  • I think your problem is that you’re trying to create multiple audioOuts, this is the last point in the chain and just connects to the OS audio. So it wouldn’t matter how many pieces of audio you want to play back simultaneously you would only have one audio output. - I use ofxPD so the audio processing in my projects happen in pd and then are outputted to the audioOut

In ofsoundstreamsetup you probably want 2 channels this means that you get stereo, otherwise you’d just get mono, probably only out of the left speaker/earphone.

I think you might be setting the input to 0 because of the 2 else {memset()} arguments in audioIn. You should only have 1 which gets called if neither bRecording are true

hth
Miles