aaronaanderson / ofxPortSF

ofxPortSF is an addon to aid in loading, recording, and saving sound files for projects that implement an audio stream explicitly.
10 stars 2 forks source link

Saved wav not loading #1

Open jamesalliban opened 7 years ago

jamesalliban commented 7 years ago

Hi Aaron

Nice addon. All seems fine apart from the fact that I cannot load a .wav file that was saved using the same app. Not a big deal as .aif is working perfectly but thought I'd bring it to your attention. I've made an app that combines your 3 examples. Code here:

ofApp.cpp:

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup()
{
    ofBackground(40);
    props.chans = 1;// monophonic 
    props.samptype = PSF_SAMP_32;// 32 bits
    props.srate = 48000;//Sampling rate of recording

    isRecording = false;

    ofSoundStreamSetup(2, 2, 48000, 512, 4);//setup for stereo system
}

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

}

//--------------------------------------------------------------
void ofApp::draw(){
    string text = "fps:" + ofToString(ofGetFrameRate()) + "\n\n";
    text += "' ' = record\n";
    text += "'s' = stop recording\n";
    text += "'l' = load\n";
    text += "isRecording: " + ofToString(isRecording ? "yes" : "no");
    ofDrawBitmapStringHighlight(text, 10, 50);
}

void ofApp::audioIn(float* input, int bufferSize, int nChannels)
{
    float maxValue = 0;
    float average = 0;
    for (int i = 0; i < bufferSize * nChannels; i++)
    {
        if (isRecording) {
            psf_sndWriteFloatFrames(ofd, &input[i], 1);//add the current sample to the current recording
        }

    }
    average /= bufferSize;
}

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

    cout << "nChannels = " << nChannels << endl;
    for (int i = 0; i < bufferSize; i++) {

        /*sound file player that can adapt to number of channels in audio file
        this ignores sample rate. If the sample rate of the file is different than the sample rate of your DAC,
        playback will be at the wrong speed. This is just to demonsrate.
        Also, this will crash if you attempt to play a soundfile with more channels than your playback.*/
        if (playSound) {
            for (int j = 0; j < soundFileProperties.chans; j++) {//for every sample in a frame (2 if stereo, for example)
                output[i*nChannels + j] = soundFile[playIndex + j] * 1.0;//interleave samples into audio buffer
            }

            playIndex += soundFileProperties.chans;//skip ahead one frame
            if (playIndex >= totalFramesRead) {//if sound file is finished,
                playIndex = 0;//start over
            }
        }//end of sound player

    }//end of audio buffer loop
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key)
{
    if (key == ' ')
    {

        recording.clear();
        playSound = false;

        ofFileDialogResult saveFileResult = ofSystemSaveDialog("defaultName.wav", ".wav or .aif");

        string path = saveFileResult.getPath();// store path
        //string path = ofToDataPath("sound.aif");
        const char *filePath = path.c_str();// convert from fancy string to C string

        outputFormat = psf_getFormatExt(filePath);//grab the output format

        switch (outputFormat) {
        case PSF_FMT_UNKNOWN://unknown format or no format given
            ofSystemAlertDialog("Not a recognized format, try .wav or .aif");
            break;//give up
        default:
            props.format = outputFormat;//set the given format to the write format
            ofd = psf_sndCreate(filePath, &props, 0, 1, PSF_CREATE_RDWR);//create sound file of specified type
            isRecording = true;//start writing data
        }

        isRecording = true;
    }
    else if (key == 's') 
    {
        isRecording = false;//stop data from being written
        psf_sndClose(ofd);//close sound file
        isRecording = false;
    }
    else if (key == 'l') 
    {
        ofFileDialogResult loadFileResult = ofSystemLoadDialog();//open the load dialog
        string path = loadFileResult.getPath();//store the string
        const char *filePath = path.c_str();// convert from fancy string to C string

        ifd = psf_sndOpen(filePath, &soundFileProperties, 0);//open the sound file

        if (ifd < 0) {//this can happen if the file does not exist or the format is not supported
            ofSystemAlertDialog("Error loading file");
        }
        else {
            frame = (float*)malloc(soundFileProperties.chans * sizeof(float));//set the size of frame to be the nSamples per Frame
            framesRead = psf_sndReadFloatFrames(ifd, frame, 1);//grab the first frame
            totalFramesRead = 0;
            soundFile.clear();//clear the vector that the soundFile will be stored in
            while (framesRead == 1) {//while there are still frames to be read
                totalFramesRead++;//keep track of number of frames;
                for (int i = 0; i < soundFileProperties.chans; i++) {//for every sample in the frame
                    soundFile.push_back(frame[i]);//add frame to the soundFile vector
                }
                framesRead = psf_sndReadFloatFrames(ifd, frame, 1);//returns 1 if there are still more frames
                                                                   //cout << framesRead << " " << endl;
            }
            playIndex = 0;//start sound from beginning
            playSound = true;//start playing the sound once loaded
        }
    }
}

ofApp.h:

#pragma once

#include "ofMain.h"
#include "ofxPortSF.h"

class ofApp : public ofBaseApp{

    public:
        void setup();
        void update();
        void draw();
        void audioIn(float* input, int bufferSize, int nChannels);
        void audioOut(float * output, int bufferSize, int nChannels);
        void keyPressed(int key);

        vector<float> recording;

        ofSoundStream soundStream;

        bool isRecording;
        bool isPlaying;
        int currentSample;

        PSF_PROPS props;//store sound file properties
        int ofd = -1;//to keep track if opened, and what error if not I think (could be wrong)
        psf_format outputFormat = PSF_FMT_UNKNOWN;//this should be changed if file extension is accepted

                    //Used for loading sound
        PSF_PROPS soundFileProperties;//will be auto-populated when file loaded
        long framesRead, totalFramesRead;//framesread used to check if there are still more frames in file
        int ifd = -1;//identification for the sound file, used by the library
        float* frame = NULL;//location of currently read frame
        vector<float> soundFile;//actual stored sound file

                                //used for playing sound
        bool playSound;//on/off toggle
        unsigned int playIndex;//location of needle head
};
aaronaanderson commented 7 years ago

@jamesalliban,

Thank you for bringing this to my attention; the error is certainly a bit strange. I'll look at this as soon as possible and upload a fix along with a threaded sound file loader!

Thanks again,

Aaron