編集履歴一覧に戻る
lipoyangのアイコン画像

lipoyang が 2025年01月14日21時47分32秒 に編集

コメント無し

本文の変更

# コンセプト

-

大正琴という楽器をご存じでしょうか? 大正琴は大正時代に考案された楽器で、左手で鍵盤を押さえ、右手のピックで弦を弾いて演奏するのが特徴です。現在ではアンプで音を増幅する電気大正琴や、シンセサイザーでさまざまな音色を出せる電子大正琴も存在します。

+

大正琴という楽器をご存じでしょうか? 大正琴は大正時代に考案された楽器で、左手で鍵盤を押さえ、右手のピックで弦を弾いて演奏するのが特徴です。現在ではアンプで音を増幅する電気大正琴や、シンセサイザーでさまざまな音色を出せる電子大正琴も存在します。

![大正琴](https://camo.elchika.com/9c415448bb1a35b2b66dee092f042749965ded6c/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65363836663263622d316331322d343731392d623966382d3934363239653238386636312f36303539333464372d386264382d343539372d383033642d303135663561636436323261/) 「大正こンパクと」は省スペースを追求した新しい電子大正琴です。8個のキーと4本の弦で2オクターブ以上の音域をカバーします。 # 動画 @[youtube](https://www.youtube.com/watch?v=B-H45Hiuvkg) # 仕様 「大正こンパクと」は ①~⑧の8個のキーと、G線・D線・A線・E線の4本の弦を持ちます。各弦の音域は、G線がG3~D4、D線がD4~A4、A線がA4~E5、E線がE5~B5です。詳しくは下表に示します。 ![キャプションを入力できます](https://camo.elchika.com/f359d23645113bce001b23ff9b2e4e54902b48ea/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65363836663263622d316331322d343731392d623966382d3934363239653238386636312f66653235376433392d313231652d346262632d616535352d626430326366393436613762/) 4本の弦の振動をエレキギター用のピックアップで検出しますが、弾かれたことを検出するためのセンサーであり、正確な調律は不要です。スピーカに出力する音は、上記の表にしたがった音程をデジタルで生成します。音の生成にはサンプリング音源データを用い、琴の音色を再現します。 ![キャプションを入力できます](https://camo.elchika.com/aa65b05e774370d49a2d5bdaa239ff09b754b012/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65363836663263622d316331322d343731392d623966382d3934363239653238386636312f63623938623038632d373832652d346438352d386161342d343634643266636631636634/) 以上の仕様を実装するため、マイコンボードは SPRESENSE を使用しました。 SPRESENSEの拡張ボードは スピーカ出力端子やマイク端子、マイクロSDカードスロットを備えており、またオーディオ系や楽器作りのための豊富なライブラリとサンプルコードも用意されているためです。ピックアップはSPRESENSEのマイク端子に接続します。 # ハードウェア ## 主な部品 - SPRESENSEメインボード および 拡張ボード - ピックアップ (4弦エレキギター用) - D級アンプモジュール (PAM8403使用) - スピーカ - メカニカルキースイッチ : Cherry MXスイッチ (赤軸) - エレキギターの弦 : D'Addario EXL110 - マイクロSDカード - DC/DCコンバータ DC4.5~9V → DC5V / 1A ## 結線 ![キャプションを入力できます](https://camo.elchika.com/562f3e63465e5370ce7063b7c69b4f10813ae874/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65363836663263622d316331322d343731392d623966382d3934363239653238386636312f61613139636365612d363235652d343037332d386561612d386263383733306439313665/) # ソフトウェア ## 開発環境 - IDE : PlatformIO (詳しくは→ [PlatformIO で Spresense](https://lipoyang.hatenablog.com/entry/2024/11/12/201737) ) - フレームワーク : Arduino - 依存ライブラリ : ssprocLib ## 構成 ![キャプションを入力できます](https://camo.elchika.com/66b77567953cdaea9870fa81aee889b976622cbb/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65363836663263622d316331322d343731392d623966382d3934363239653238386636312f37333036353132622d363731332d343265382d396334312d613962396334623664376230/) ## 弦の振動の検出 SPRESENSEで簡単に楽器を開発するライブラリとして、[Sound Signal Processing Library for Spresense](https://github.com/SonySemiconductorSolutions/ssih-music/) (ssprocLib) が提供されています。ssprocLib の VoiceCapture クラスはマイク端子から入力された音声信号の周波数と音量を解析します。これを利用してピックアップで拾った弦の振動の周波数を解析し、どの弦が弾かれたかを判定します。 VoiceCaptureクラスはメインコアとサブコアが協調動作するようになっており、メインコアでマイク入力をバッファし、サブコアでFFT(周波数解析)を演算します。サブコア側のプログラムは、ssprocLib のサンプルコードの YuruHorn_SubCore1.ino をベースに修正したものを使用します。YuruHorn_SubCore1.ino は人の声を入力するためのものなので、周波数のパラメータなどを変更しました。 メインコア側のプログラムは、VoiceCaptureクラスを継承した Kompactoクラスを作成し、鍵盤入力も受けてノートオン/ノートオフを発行するようにしました。 ```cpp:Kompacto.h #pragma once #include <VoiceCapture.h> // 「大正こンパクと」クラス // VoiceCaptureクラスを継承 (マイク入力からピーク周波数と音量を取得できる) class Kompacto : public VoiceCapture { public: // コンストラクタで鍵盤のピン番号、各弦の周波数、後段を指定 Kompacto(const int* pin_keyboard, const float* f_strings, Filter& filter) : VoiceCapture(filter), PIN_KEYBOARD(pin_keyboard), FREQ_STRINGS(f_strings) {}; // 開始処理をオーバーライド bool begin() override; protected: // サブコアからピーク周波数検出を受けるコールバックをオーバーライド // freq_number : 周波数の分子 // freq_denom : 周波数の分母 (freq_number / freq_denom が Hz単位になる) // volume : 音量 void onCapture(unsigned int freq_numer, unsigned int freq_denom, unsigned int volume) override; private: const int* PIN_KEYBOARD; // キーボードのピン番号のテーブル const float* FREQ_STRINGS; // 弦の周波数のテーブル unsigned int _prev_volume; // 前回の音量 int _detect_cnt; // 有効な検出の連続カウンタ int _last_note; // 各弦の最後の音符 }; ``` ## 琴の音の生成 ssprocLib の SFZSink クラスはSFZ形式のサウンドフォントを利用でき、簡単にサンプリング音源を実装できます。ただし、SFZSink で扱える SFZ にはかなり制約があります。そこで、SFZSink で扱えるSFZに変換するスクリプト [import-sfz.py](https://github.com/SonySemiconductorSolutions/ssih-music/tree/develop/tools) が提供されています。 琴の音色のSFZデータとして、SFZ Instruments から [13 Strings KOTO (Ui_KOTO)](https://sfzinstruments.github.io/folk/koto/) のデータをダウンロードして利用しました。Ui_KOTO には13弦琴の多様な奏法のSFZデータが収録されていますが、その中でもいちばんふつうの奏法のデータと思われる(?) Sustain_Front.sfz を上記の import-sfz.py で変換しました。 ところが、変換した SFZ を SFZSink に与えても音が再生できません。 SFZファイルを確認したところ、かなり複雑な指定がされていました。そこで、サンプルコード用の音源ファイル([assets.zip](https://github.com/SonySemiconductorSolutions/ssih-music/releases/latest/download/assets.zip)) の SawLpf.sfz を参考に手作業で簡単なSFZファイルを作成したところ、再生できました。ポイントとして、SawLpf.sfz は持続的なノコギリ波の音色なので loop_mode=loop_continuous ですが、琴は撥弦楽器であり持続しないので loop_mode=no_loop としました。それにともない、loop_start や loop_end もなくしました。サンプル音源データ(WAVファイル)は、 import-sfz.py で変換されたものを使用しました。 ```xml:koto.sfz <group> loop_mode=no_loop <region> key=50 sample=Koto/050050_Front_d3_Sustain1.wav <region> key=51 sample=Koto/051051_Front_d#3_Sustain1.wav <region> key=52 sample=Koto/052052_Front_e3_Sustain1.wav <region> key=53 sample=Koto/053053_Front_f3_Sustain1.wav <region> key=54 sample=Koto/054054_Front_f#3_Sustain1.wav <region> key=55 sample=Koto/055055_Front_g3_Sustain1.wav <region> key=56 sample=Koto/056056_Front_g#3_Sustain1.wav <region> key=57 sample=Koto/057057_Front_a3_Sustain1.wav <region> key=58 sample=Koto/058058_Front_a#3_Sustain1.wav <region> key=59 sample=Koto/059059_Front_b3_Sustain1.wav <region> key=60 sample=Koto/060060_Front_c4_Sustain1.wav <region> key=61 sample=Koto/061061_Front_c#4_Sustain1.wav <region> key=62 sample=Koto/062062_Front_d4_Sustain1.wav <region> key=63 sample=Koto/063063_Front_d#4_Sustain1.wav <region> key=64 sample=Koto/064064_Front_e4_Sustain1.wav <region> key=65 sample=Koto/065065_Front_f4_Sustain1.wav <region> key=66 sample=Koto/066066_Front_f#4_Sustain1.wav <region> key=67 sample=Koto/067067_Front_g4_Sustain1.wav <region> key=68 sample=Koto/068068_Front_g#4_Sustain1.wav <region> key=69 sample=Koto/069069_Front_a4_Sustain1.wav <region> key=70 sample=Koto/070070_Front_a#4_Sustain1.wav <region> key=71 sample=Koto/071071_Front_b4_Sustain1.wav <region> key=72 sample=Koto/072072_Front_c5_Sustain1.wav <region> key=73 sample=Koto/073073_Front_c#5_Sustain1.wav <region> key=74 sample=Koto/074074_Front_d5_Sustain1.wav <region> key=75 sample=Koto/075075_Front_d#5_Sustain1.wav <region> key=76 sample=Koto/076076_Front_e5_Sustain1.wav <region> key=77 sample=Koto/077077_Front_f5_Sustain1.wav <region> key=78 sample=Koto/078078_Front_f#5_Sustain1.wav <region> key=79 sample=Koto/079079_Front_g5_Sustain1.wav <region> key=80 sample=Koto/080080_Front_g#5_Sustain1.wav <region> key=81 sample=Koto/081081_Front_a5_Sustain1.wav <region> key=82 sample=Koto/082082_Front_a#5_Sustain1.wav <region> key=83 sample=Koto/083083_Front_b5_Sustain1.wav <region> key=84 sample=Koto/084084_Front_c6_Sustain1.wav ``` ## スケッチ ```cpp:main.cpp #include <SFZSink.h> #include "Kompacto.h" // 鍵盤のキー1~8のピン番号 static const int PIN_KEYBOARD[] = { PIN_D00, PIN_D01, PIN_D02, PIN_D03, PIN_D04, PIN_D05, PIN_D06, PIN_D07 }; // 各弦の判定周波数[Hz] (音階とは特に関係なく、調整しやすい周波数でよい) static const float FREQ_STRINGS[]={

-

1125.0F, // G線 1453.0F, // D線 1593.0F, // A線 1687.0F, // E線

+

1000.0F, // G線 1500.0F, // D線 2000.0F, // A線 2500.0F, // E線

}; // 琴のSFZデータを指定してSinkを生成 SFZSink sink("Koto.sfz"); // 定数とSinkを指定して楽器を生成 Kompacto inst(PIN_KEYBOARD, FREQ_STRINGS, sink); // 初期化 void setup() { // 楽器の初期化 if (!inst.begin()) { Serial.println("ERROR: init error."); while (true) delay(1000); } } // メインループ void loop() { // 楽器の更新 inst.update(); } ``` # 筐体 筐体はAutodesk Fusionで設計し、厚さ4mmのMDFをレーザーカットして組み立てて、塗装して仕上げました。 また、将来の機能追加のため、128×64ピクセルの1.3インチOLEDと、スイッチ付きロータリーエンコーダを設けました。 ![3Dモデルの設計](https://camo.elchika.com/10dbfa93ce1c315637dbfb6cf468d67f9b936f74/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65363836663263622d316331322d343731392d623966382d3934363239653238386636312f62323561643063662d653762632d346662362d386436342d346138346535383934623835/) ![MDFをカットして組み立て](https://camo.elchika.com/8e3f57f9d8759a1a5c22f952a64885d1520a6f21/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f65363836663263622d316331322d343731392d623966382d3934363239653238386636312f38346138626234622d633938312d343634312d613765632d653631393963303730653930/) # GitHubリポジトリ https://github.com/lipoyang/Kompacto