Teensy Audioテスト(2)

投稿者: | 2020年5月23日

Tennsy Audioの続きです。再び先の動画を参照しながら進めます。

物理的な配線は前回と同じ、下記の通りです。

  • スイッチ0、1、2 ⇒ Pin0、Pin1、Pin2
  • ノブ1、2、3 ⇒ Pin15(A1:オーディオボード上)、Pin16(A2)、Pin(A3)

一方ソフト的には、今回からAudio System Design Toolというのが新たに登場します。これはブラウザベースのGUIツールで、音声信号のルーティングをデザインするものです。音源から始まり、エフェクトやミキサーを通して最終的にアウトプットに至ります。なんかReaktorみたいでシンセデザインぽくなってきましたね。

ルーティングが出来たら、それをコードとしてエクスポートしArduino IDEでスケッチの中にコピーしてTeensyに書き込みます。つまりこのデザインツールだけでスケッチ全体が自動生成されるわけでは残念ながらありません。

Part_2_01_First_Design_Tool_Use

このツールを使った最初のサンプルスケッチは、Arduino IDEのファイル>スケッチ例>Audio>Tutrial>Part_2_01_First_Design_Tool_Useです。やってる事はSDカードにある3曲目を繰り返し再生しているだけです。

デザインツールのルーティングも下図の通り最もシンプルなものです。基本的に音声信号は左から右に流れますが、インプットとアウトプットしかありません。

右の【playSdWav】はSDカード内のWAVファイルで、今回は1つのファイルしか扱わないので一つだけです。左側の【i2s1】はオーディオボードのアウトプット(L/R)です。そして下で浮いてる【sgtl5000】はオーディオボードのチップを表してるそうです。

ここまで作ったらツール上部の「Export」ボタンを押し、出てきたコードをコピーします。それをスケッチの// copy the Design Tool code here以下にペーストすればOKです。ペーストした部分だけを抜き出すと以下のようになります。


#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h> 

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=320,326
AudioOutputI2S           i2s1;           //xy=536,340
AudioConnection          patchCord1(playSdWav1, 0, i2s1, 0);
AudioConnection          patchCord2(playSdWav1, 1, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=398,410
// GUItool: end automatically generated code

Part_2_02_Mixers

次のスケッチPart_2_02_MixersはDJミキサーのように1つのノブで2つの曲を切り替えます。デザインツールでは下図のようにMixerオブジェクトを使います。Mixerひとつはモノチャンネルですが、入力は最大4つ可能です。

例えば【playSdWav1】のLチャンネルをMixer1に入れたとすると、RチャンネルはMixer2へ。【playSdWav2】も同様にLをMixer1、RをMixer2に繋ぎます。つまりMixer1/Mixer2はミックスバスのようなもので、2つの音源(チャンネル)がミックスされ最終的に出力されるわけです。

これでコードを生成しスケッチに張り付けると次のようになります。

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=307,421
AudioPlaySdWav           playSdWav2;     //xy=314,521
AudioMixer4              mixer1;         //xy=530,405
AudioMixer4              mixer2;         //xy=564,510
AudioOutputI2S           i2s1;           //xy=799,403
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer2, 0);
AudioConnection          patchCord3(playSdWav2, 0, mixer1, 1);
AudioConnection          patchCord4(playSdWav2, 1, mixer2, 1);
AudioConnection          patchCord5(mixer1, 0, i2s1, 0);
AudioConnection          patchCord6(mixer2, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=443,765
// GUItool: end automatically generated code


// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

void setup() {
  Serial.begin(9600);
  AudioMemory(8);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  mixer1.gain(0, 0.5);
  mixer1.gain(1, 0.5);
  mixer2.gain(0, 0.5);
  mixer2.gain(1, 0.5);
  delay(1000);
}

void loop() {
  if (playSdWav1.isPlaying() == false) {
    Serial.println("Start playing 1");
    playSdWav1.play("SDTEST1.WAV");
    delay(10); // wait for library to parse WAV info
  }
  if (playSdWav2.isPlaying() == false) {
    Serial.println("Start playing 2");
    playSdWav2.play("SDTEST4.WAV");
    delay(10); // wait for library to parse WAV info
  }  // uncomment this code to allow Knob A3 to pan between songs
  int knob = analogRead(A3);  // knob = 0 to 1023
  float gain1 = (float)knob / 1023.0;
  float gain2 = 1.0 - gain1;
  mixer1.gain(0, gain1);
  mixer1.gain(1, gain2);
  mixer2.gain(0, gain1);
  mixer2.gain(1, gain2);
}

オリジナルスケッチでは

// uncomment this code to allow Knob A3 to pan between songs

以下はコメントアウトされていましたが、ここでは最初からアンコメントしています。やっていることは、ノブ3を左一杯に回せば(読み取り値がゼロなら)SDTEST1.WAVだけが再生され、右に回していくと徐々にSDTEST4.WAVの割合が増え、右一杯回し切れば(読み取り値が最大なら)SDTEST4.WAVだけが再生されます。

元のスケッチはコメントアウトされているのでミックス機能は無く、2つの曲が同じ音量で張り続けるだけです。コードとしてはsetup()の中の以下の部分でゲインを固定しています。

mixer1.gain(0, 0.5); mixer1.gain(1, 0.5); mixer2.gain(0, 0.5); mixer2.gain(1, 0.5);

Part_2_03_Samples

これまではSDカード内の音声ファイルを扱ってきましたが、このスケッチではTeensyのメモリに直接音声ファイル(サンプルネタ的な短い音)を読み込みます。

従ってデザインツールのルーティングは次のようになります。ソースがplaySdWavからplayMemに変わっていますが他は同じです。

これをまたExportしてスケッチに組み込んだのが次のコードです。冒頭で幾つかのライブラリをインクルードしていますが、夫々にドラムのワンショットサンプルが含まれているようです。Arduino IDEでこのスケッチを開くと、スケッチ自体のタブの他に幾つもタブが出てきますが、中を見ると何とWAVファイルをバイナリに変換した生データです。

// WAV files converted to code by wav2sketch
#include "AudioSampleSnare.h"        // http://www.freesound.org/people/KEVOY/sounds/82583/
#include "AudioSampleTomtom.h"       // http://www.freesound.org/people/zgump/sounds/86334/
#include "AudioSampleHihat.h"        // http://www.freesound.org/people/mhc/sounds/102790/
#include "AudioSampleKick.h"         // http://www.freesound.org/people/DWSD/sounds/171104/
#include "AudioSampleGong.h"         // http://www.freesound.org/people/juskiddink/sounds/86773/
#include "AudioSampleCashregister.h" // http://www.freesound.org/people/kiddpark/sounds/201159/
#include <Bounce.h> 


///////////////////////////////////
// copy the Design Tool code here
///////////////////////////////////
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h> 

// GUItool: begin automatically generated code
AudioPlayMemory          playMem4;       //xy=316,401
AudioPlayMemory          playMem2;       //xy=319,278
AudioPlayMemory          playMem3;       //xy=320,339
AudioPlayMemory          playMem1;       //xy=322,215
AudioMixer4              mixer1;         //xy=518,302
AudioOutputI2S           i2s1;           //xy=709,301
AudioConnection          patchCord1(playMem4, 0, mixer1, 3);
AudioConnection          patchCord2(playMem2, 0, mixer1, 1);
AudioConnection          patchCord3(playMem3, 0, mixer1, 2);
AudioConnection          patchCord4(playMem1, 0, mixer1, 0);
AudioConnection          patchCord5(mixer1, 0, i2s1, 0);
AudioConnection          patchCord6(mixer1, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=544,451
// GUItool: end automatically generated code

// Bounce objects to read pushbuttons 
Bounce button0 = Bounce(0, 15);
Bounce button1 = Bounce(1, 15);  // 15 ms debounce time
Bounce button2 = Bounce(2, 15);

void setup() {
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);
  AudioMemory(10);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.5);
  mixer1.gain(0, 0.8);
  mixer1.gain(1, 0.8);
  mixer1.gain(2, 0.8);
  mixer1.gain(3, 0.8);
}

void loop() {
  // Update all the button objects
  button0.update();
  button1.update();
  button2.update();

  if (button0.fallingEdge()) {
    playMem1.play(AudioSampleSnare);
  }
  if (button1.fallingEdge()) {
    playMem2.play(AudioSampleTomtom);
  }
  if (button2.fallingEdge()) {
    playMem3.play(AudioSampleHihat);
  }

/*Switch 2 drum sets by knob3*/
  int knob = analogRead(A3);
  if (button0.fallingEdge()) {
    if (knob < 512) {
      playMem1.play(AudioSampleSnare);
    } else {
      playMem1.play(AudioSampleKick);
    }
  }
  if (button1.fallingEdge()) {
    if (knob < 512) {
      playMem2.play(AudioSampleTomtom);
    } else {
      playMem4.play(AudioSampleGong);
    }
  }
  if (button2.fallingEdge()) {
    if (knob < 512) {
      playMem3.play(AudioSampleHihat);
    } else {
      playMem3.play(AudioSampleCashregister);
    }
  }

}

ここでやっていることは、3つのサンプルを3つのスイッチにアサインして押すと鳴る。つまりサンプラーです。ただオリジナルのスケッチでは”/*Switch 2 drum sets by knob3*/”(私が追記)以下の部分がコメントアウトしてあったので、それを外して動くようにしています。

何をしているかというと、ノブ3を左右に回す事でドラムセットを切り替えているのです。ノブの位置が真ん中より右なら最初の3つのサンプルが、真ん中より左なら後半の3つサンプルが鳴ります。つまりここでのノブ3はアナログ制御ではなく切り替えスイッチとして使っているだけです。

実際にどうなるか撮影したのが下のビデオです。ピンボケですみませんが、音はPCでライン録音しているのでオリジナルに近いです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です