【Arduino UNO R4】エフェクター的なものを作る試み(リバーブ)

いつものようにまずはリバーブから。

youtu.be

割込みでADしている関係でサンプリング周波数は22,050Hz。DMAでごにょごにょできればもう少し周波数をあげられるのではないかと。DACが一つなので出力はモノラル。

【Arduino UNO R4】エフェクター的なものを作る試み(スルー)

Arduino UNO R4はCPUも変わったしDACも搭載されてるってことで、エフェクター的なものにトライ。とりあえずADしてDAするだけのスルー状態で盛大にノイズ出てますけど、明日の自分のためにメモ。物忘れがひどい…

逆相とMIXすることで、ヒュイィーンという刺激的なノイズは減少してホワイトノイズっぽくなったけど、まだまだノイズ多し

バラック

回路図(バラックと大分違う)

フィルタと電源あたりは後でキチンと考える

ソースコード

#include "AGTimerR4.h"

#define FREQ_SAMPLING 22050.0f
#define ADC_RESOLUTION 14
#define DAC_RESOLUTION 12
#define DAC_OFFSET 2048

volatile bool samplingStat = false;

void timerCallback() {
  samplingStat = true;
}

void setup() {
  analogReadResolution(ADC_RESOLUTION);
  analogWriteResolution(DAC_RESOLUTION);

  AGTimer.init(FREQ_SAMPLING, timerCallback);
  AGTimer.start();
}

void loop() {
  while(!samplingStat);

  int rd = analogRead(A1) - analogRead(A2);
  int wd = signalProcessing(rd);
  analogWrite(DAC, (wd >> (ADC_RESOLUTION - DAC_RESOLUTION + 1)) + DAC_OFFSET);

  samplingStat = false;
}

int signalProcessing(int rd) {
  return rd;
}

バッファリングしてDMAでドカドカと転送できるように後で検討(後でが多い)

【Arduino UNO R4】タイマーライブラリ作りました

Arduino UNO R4 で タイマー割り込みを処理するだけのライブラリを作りました。

あれこれ調べた結果は別エントリーにまとめます(多分)

github.com

覚え書き

init(period, div, timerCallback)

この関数のdivで有効な値は以下の4つです。

  • TIMER_SOURCE_DIV_1
  • TIMER_SOURCE_DIV_2
  • TIMER_SOURCE_DIV_8
  • TIMER_SOURCE_DIV_64

ただTIMER_SOURCE_DIV_64のときだけトリッキーな動きをするので、他の2つのinit()を使うのが安心です(今のところ)

【Processing】ファイル選択ダイアログ

Processingでファイル選択ダイアログを使用する方法をメモっておきます。 入力はselectInput()、出力はselectOutput()でダイアログを表示。ファイル選択後はコールバック関数が呼び出されます。

構文

selectInput(prompt, callback)
selectOutput(prompt, callback)

※ 詳しい設定はselectInputのリファレンスselectOutputのリファレンスを参照

パラメータ

prompt
プロンプト(windowsではダイアログのタイトルバーに表示される文字列)
callback
ファイル選択後に呼び出されるコールバック関数名

戻り値

ありません

コールバック関数構文

callback(File selection)

ダイアログをキャンセルしたり閉じたりした場合にはselectionはnull、選択された場合にはselection.getAbsolutePath()でフルパスが取得できます

ウィンドウをクリックするとファイル出力ダイアログが表示されます。

void setup()
{
  size(400,400); 
}

void draw()
{
}

void mousePressed()
{
  selectOutput("Select a file to process:", "fileSelected");
}

void fileSelected(File selection) 
{
  if (selection == null) 
  {
    println("Window was closed or the user hit cancel.");
  } 
  else
  {
    println("User selected " + selection.getAbsolutePath());
  }
}

【Raspberry Pi Pico】TinyUSBでMIDI受信

恐る恐るRaspberry Pi PicoのSDKにあるTinyUSBをつかってみたら、恐ろしく簡単にMIDI受信できました。

プロジェクトの作成

pico-sdkのtinyusbにMIDI送信のサンプルプログラムmidi_testがあるので、これをベースにMIDI受信用プロジェクトを作成します。 ファイルの構成は以下の通りです。

usb_midi
    ├─ CMakeLists.txt
    ├─ pico_sdk_import.cmake
    ├─ tusb_config.h
    ├─ usb_descriptors.c
    └─ main.c
  1. 適当な場所にフォルダ作成。今回はusb_midiとしました。
  2. pico-sdk/lib/tinyusb/examples/device/midi_test/srcにある3つのファイルをusb_midiフォルダにコピーします。
  3. pico-examples/pico_sdk_import.cmakeをusb_midiフォルダにコピー。
  4. 以下の内容でCMakeLists.txtを作成。
cmake_minimum_required(VERSION 3.12)

# Pull in SDK (must be before project)
include(pico_sdk_import.cmake)

project(usb_midi C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})

# Initialize the SDK
pico_sdk_init()

set(CMAKE_C_FLAGS_DEBUG "-O0 -g")

add_executable(usb_midi
        main.c
        usb_descriptors.c
        )

target_include_directories(usb_midi PRIVATE ${CMAKE_CURRENT_LIST_DIR})

target_link_libraries(usb_midi PRIVATE
    pico_stdlib
    tinyusb_device
    tinyusb_board)
pico_add_extra_outputs(usb_midi)

# Copy uf2 when the build is complete
add_custom_command(
  TARGET usb_midi
  POST_BUILD
  COMMAND copy ${CMAKE_CURRENT_BINARY_DIR}\\usb_midi.uf2 f:\\
)

MIDI受信用コード

コピーしたサンプルプログラムをそのままビルドすると、シーケンサー的にNoteOn/Offが送信されます。これを変更してNoteOn/Offを受信した時にLEDがついたり消えたりするようにしてみました。

#include "bsp/board.h"
#include "tusb.h"

void midi_task(void)
{
  uint8_t n_data;
  uint8_t msg[4];
  while (tud_midi_available())
  {
    if (n_data = tud_midi_read(msg, 3)) 
    {
      switch (0xf0 & msg[0])
      {
        case 0x80:    // NoteOff
          board_led_off();
          break;
        case 0x90:    // NoteOn
          if (msg[2] == 0)  board_led_off();    // velocity == 0 --> NoteOff
          else              board_led_on();
          break;
        default:
          break;
      }
    }
  }
}

int main(void)
{
  board_init();
  tusb_init();

  while (1)
  {
    tud_task(); // tinyusb device task
    midi_task();
  }

  return 0;
}

tud_midi_available()でデータがあればtud_midi_read()でデータを取り出して、あとはメッセージの種類に応じて処理するだけ。

【Raspberry Pi Pico】Arduino IDEにボード追加/動作確認

そこそこ苦労してC++用の開発環境を構築し終えたあたりで、Arduino IDEがpicoをサポートしたという情報をキャッチしたわけで…。試してみました。使用したArduinoIDEのバージョンは1.8.13です。

2種類の追加ボード

2021年4月24日現在、2種類のpico用の追加ボードがあります。 f:id:washiyamagiken:20210424230508p:plain

  1. Raspberry Pi Pico/RP2040
  2. Arduino Mbed OS RP2040 Boards

2がArduino公式サポート版のようですが、先行して発表された1の方が完成度が高い感じがします。

Raspberry Pi Pico/RP2040 のインストールと動作確認

まずは1のRaspberry Pi Pico/RP2040の方から。 f:id:washiyamagiken:20210424231240p:plain

  1. “File>Preferences”のAdditional Boards Manager URLs:に https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json を追加
  2. “Tools>Board>Boards Manager...”で“Raspberry Pi Pico/RP2040”をインストール
  3. “File>Examples”にpico用のサンプルが多数ありますが、とりあえず“Blink”で動作確認
  4. BOOTSELボタンを押したままUSBケーブルをPCに接続して本体をマウント(初回はこれが必要!)
  5. “Sketch>Upload”を選択してコンパイル。完了するとマウントされたpicoにuf2ファイルがコピーされ実行されます
  6. 1度ビルドすると“Tools>Port”が有効になるので、ここでpicoのポートを選択
  7. 2回目のアップロードからは自動的にpicoがマウントされて実行まで進むようになります。あぁ楽チン

Arduino Mbed OS RP2040 Boards のインストールと動作確認

片一方だけインストールすれば事足りますけど、もう一つのArduino Mbed OS RP2040 Boardsも。 f:id:washiyamagiken:20210424232845p:plain

  1. “Tools>Board>Boards Manager...”で“Arduino Mbed OS RP2040 Boards”をインストール
  2. “File>Examples”に追加されるサンプルは3つだけ。こちらもとりあえず“Blink”
  3. こちらは毎回BOOTSELボタン云々で本体をマウントする必要があります
    ※ 自動的にでマウントされるような記述をどこかで見たんですけどアタクシの環境ではダメでした
  4. “Sketch>Upload”でコンパイル完了後、uf2ファイルがコピーされて実行されます

比較

  1. Raspberry Pi Pico/RP2040
  2. Arduino Mbed OS RP2040 Boards

2つを比較すると、公式の方が若干コンパイルが早いような気がします。先日構築したC++の開発環境に比べると圧倒的に遅いですけど…。

サンプルの充実度、ボードの設定パラメータの豊富さ、自動的に本体をマウントして実行まで進むあたりを考えるとRaspberry Pi Pico/RP2040の方を使うかなー。

Mbedがよくわかってないんですが、公式の方はMbedのライブラリ等の資産が使えたりとか多大なメリットがあるんでしょうか?

【Raspberry Pi Pico】UDA1334Aでsine出力

PCM5102Aとつないでsineが問題なく出力できたわけですが、 もう一つDACコレクションの中からUDA1334A を引っ張り出してきて試してみました。

使用したDACボードはデフォルトでI2Sフォーマット(SF0とSF1がLOW)なので、PCM5102Aの時と同様3本接続するだけです。

GP26 ---> BCLK
GP27 ---> WSEL
GP28 ---> DIN

f:id:washiyamagiken:20210420231554j:plain こちらも問題なし! と思ったんですけど、PCM5102Aの時と比べると振幅が半分…。要調査ですね。