simple sampler by raspberrypi and openFrameworks

raspberrypiとopenframeworksを使って簡単なsamplerを作った. 

# 環境
raspberrypi
openFrameworks(for linux)

# addon
ofxGPIO

# GPIO setting

これ
<img width="712" alt="Raspberry-Pi-GPIO-pinouts.png" src="https://qiita-image-store.s3.amazonaws.com/0/102253/61b36820-e3ff-1af7-6652-111ba16096f8.png">
で
ボタンを押した時に
GPIO番号 : 役割
GPIO14 : 録音開始/録音停止ボタン
GPIO15 : 再生開始/一時停止ボタン
GPIO18 : 再生位置を最初に戻すボタン
の動作を行う様に割り当てた. 

具体的な配線は以下の通り:

PIN番号 : 色 : 役割
1 : 赤 : 3.3V
6 : 黒 : GND
8 : 黄 : 赤ボタン > GPIO14, 録音開始/録音停止ボタン
10 : 青 : 青ボタン > GPIO15, 再生開始/一時停止ボタン
12 : 黒 : 黒ボタン > GPIO18, 再生位置を最初に戻すボタン

![IMG_4339.jpg](https://qiita-image-store.s3.amazonaws.com/0/102253/1a0c7466-05e7-d696-3b25-579c04dd909a.jpeg)

![IMG_4340.jpg](https://qiita-image-store.s3.amazonaws.com/0/102253/7786053c-1ab7-3363-cd97-dbaa381bafe3.jpeg)

![IMG_4341.jpg](https://qiita-image-store.s3.amazonaws.com/0/102253/f514788f-2ba1-023b-b9a1-f86e8c4ee99c.jpeg)

![IMG_4342.jpg](https://qiita-image-store.s3.amazonaws.com/0/102253/301af55a-ecad-4574-507b-b0ba2fd1ca01.jpeg)

![IMG_4343.jpg](https://qiita-image-store.s3.amazonaws.com/0/102253/327c6ef6-5b44-b5a8-913c-37bfe5e72971.jpeg)


# codes
```main.cpp
#include "ofMain.h"
#include "ofApp.h"

//========================================================================
int main( ){
	ofSetupOpenGL(1024,768,OF_WINDOW);			// <-------- setup the GL context

	// this kicks off the running of my app
	// can be OF_WINDOW or OF_FULLSCREEN
	// pass in width and height too:
	ofRunApp(new ofApp());

}
```

```ofApp.cpp
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(0);
    gpioRececec.setup("14");
    gpioRececec.export_gpio();
    gpioRececec.setdir_gpio("in");
    gpioPlay.setup("15");
    gpioPlay.export_gpio();
    gpioPlay.setdir_gpio("in");
    gpioBack.setup("18");
    gpioBack.export_gpio();
    gpioBack.setdir_gpio("in");

    soundStream.printDeviceList();
    soundStream.setInDeviceID(0);
    soundStream.setOutDeviceID(1);
    soundStream.setup(this, 2, 1, SampleRate, BufferSizeMax, 4);
    
    mode = 0;
    
    recPos = 0;
    playPos = 0;
    recSize = 0;
}

//--------------------------------------------------------------
void ofApp::update(){
    gpioRececec.getval_gpio(recButton);
    gpioPlay.getval_gpio(playButton);
    gpioBack.getval_gpio(backButton);
    //ofLog()<<state_button;
    cout<<"R";
    cout<<recButton;
    cout<<"_P";
    cout<<playButton;
    cout<<"_B";
    cout<<backButton<<endl;

    if(recButton=="1"){
        if(mode==1){    //stop recording
            mode = 0;
            recSize = recPos;
        }else{          //start recording
            mode = 1;
            recPos = 0;
            float buffer[BufferSizeMax] = {};
        }
        playPos = 0;
        usleep(1000000);
    }else if(playButton=="1"){
        if(mode==2){    //pause
            mode = 0;
        }else{          //play (in the middle)
            mode = 2;
        }
        usleep(1000000);
    }else if(backButton=="1"){
        playPos = 0;    //return to the initial position
        //usleep(1000000);
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    if(mode == 0) {
        ofBackground(0);
        ofSetColor(255);
    }else if(mode == 1) {
        ofBackground(255, 0, 0);
        ofSetColor(255);
        cout<<"recording"<<endl;
    }else if(mode == 2) {
        ofBackground(0, 0, 255);
        ofSetColor(255);
        cout<<"playing"<<endl;
    }
    
    int ratio = BufferSizeMax / ofGetWidth();
    for (int i = 0; i < recSize; i+=ratio){
        ofDrawLine(i/ratio, ofGetHeight()/2,  i/ratio, ofGetHeight()/2+buffer[i]*500.0f);
    }
    
    if(mode==2){
        ofSetColor(0);
        for (int i = 0; i < playPos; i+=ratio){
            ofDrawLine(i/ratio, ofGetHeight()/2,  i/ratio, ofGetHeight()/2+buffer[i]*500.0f);
        }
    }
}

//--------------------------------------------------------------
void ofApp::audioIn(float * input, int bufferSize, int nChannels){
    if (mode == 1) {
        for (int i = 0; i < bufferSize*nChannels; i++){
            if(recPos<BufferSizeMax){
                buffer[recPos] = input[i];
                recPos++;
                recSize = recPos;
            } else {
                recSize = BufferSizeMax;
                mode = 0;
            }
            
        }
    }
}

void ofApp::audioOut(float *output, int bufferSize, int nChannels){
    if (mode == 2) {
        for (int i = 0; i < bufferSize; i++) {
            if(playPos<recSize){
                for(int n=0; n<nChannels; n++){
                    output[nChannels*i+n] = buffer[playPos];
                }
                playPos++;
            } else {
                mode = 0;
                playPos = 0;
            }
        }
    }
}


//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    if(key=='r'){
        if(mode==1){    //stop recording
            mode = 0;
            recSize = recPos;
        }else{          //start recording
            mode = 1;
            recPos = 0;
            float buffer[BufferSizeMax] = {};
        }
        playPos = 0;
    }else if(key=='p'){
        if(mode==2){    //pause
            mode = 0;
        }else{          //play (in the middle)
            mode = 2;
        }
    }else if(key=='P'){
        playPos = 0;    //return to the initial position
    }
}
```

```ofApp.h
#pragma once

#include "ofMain.h"
#include "ofxGPIO.h"

class ofApp : public ofBaseApp{

	public:
    void setup();
    void update();
    void draw();
 
    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y );
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void mouseEntered(int x, int y);
    void mouseExited(int x, int y);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);
    void audioIn(float * input, int bufferSize, int nChannels);
    void audioOut(float * output, int bufferSize, int nChannels);
    
    static const int SampleRate = 48000;
    static const int BufferSizeMax = SampleRate * 5;

    ofRtAudioSoundStream soundStream;
    float buffer[BufferSizeMax];
    int recPos;
    int recSize;
    int playPos;
    int mode; //0:off, 1:recording, 2:play
    GPIO gpioRec;
    string recButton;
    GPIO gpioPlay;
    string playButton;
    GPIO gpioBack;
    string backButton;
};
```

codeが雑だなーとは思うけど, すみません. 
あとでgitで直します. 

# git
https://github.com/KeitaSumiya/raspberrypi/tree/master/simple_sampler/src


# 結果
https://youtu.be/OwPcFcb6BtM