SSブログ

「SPRESENSEでデジタルエフェクターを作ろう!」ーモジュレーション系エフェクターの実現ー [SPRESENSE]

今回はエフェクター系統の最後のエフェクター、モジュレーション系エフェクターを実装していきます。

SpresenseDigitalEffector.PNG

空間系エフェクターは歪み系と空間系エフェクターの中間に接続されるエフェクータです。今回はトレモロ、ビブラート、コーラスを実装したいと思います。モジュレーション系エフェクターは正弦波で変調を加えているのが大きな特徴です。

effector_connection.png

信号処理の理論は次の本を参考にしました。音声音響信号処理の基本が身につきますのでおすすめです。






■ トレモロの信号処理

トレモロはモジュレーション系エフェクターの中で最も簡単な処理です。正弦波によって音の強弱をかえていきます。うねりのような効果が得られますが、エフェクターとしての効果は控えめな印象です。

Toremoro.png

dは通常0.3~0.6の値、周波数は数Hzに設定することが多いようです。曲にあわせて調整が必要になります。


■ トレモロの実装

正弦波の処理は時間がかかるのでCoretex M4F の浮動小数点アクセラレータを使うため、ARMが提供している数値ライブラリを用いました。実装では正弦波の周波数を4Hzで、dは0.4を設定しました。
(コードの中では、SAMPLE_SIZE と sample_size が混在していますが同じものです。そのうち整理します)

#define ARM_MATH_CM4
#define __FPU_PRESENT 1U
#include <cmsis/arm_math.h>

void signal_process(int16_t* mono_input, int16_t* stereo_output, const uint32_t sample_size) {
  
  /* clean up the output buffer */
  memset(stereo_output, 0, sizeof(int16_t)*sample_size*2);

  /* memory pool for 1.5sec (= 720*100*(1/48000)) */
  static const int lines = 100;
  static int16_t src_buf[sample_size*lines];  /* 2*720*100=144kBytes */

  /* shift the buffer data in src_buf and add the latest data to top of the bufer */
  memcpy(&src_buf[0], &src_buf[sample_size], SAMPLE_SIZE*sizeof(int16_t)*(lines-1)); 
  memcpy(&src_buf[(lines-1)*sample_size], &mono_input[0], SAMPLE_SIZE*sizeof(int16_t));

  static int theta = 0;
  const int mod_freq = 4; /* Hz */ 
  const float omega = 2.*PI*mod_freq/AS_SAMPLINGRATE_48000;
  const int sin_total_samples = AS_SAMPLINGRATE_48000/mod_freq;
  const float d = 0.4; /* amplitude of moduration */
  
  const int src_buf_end_point = lines*SAMPLE_SIZE-1;
  for (int n = SAMPLE_SIZE-1; n >= 0; --n) {
    float modulation = 1.-d*arm_sin_f32(omega*theta);
    mono_input[(SAMPLE_SIZE-1)-n] = (int16_t)(modulation*src_buf[src_buf_end_point-n]);
    if (++theta >= sin_total_samples) theta = 0;
  }
  
  /* copy the signal to output buffer */
  for (int n = SAMPLE_SIZE-1; n >= 0; --n)  {
    stereo_output[n*2] = stereo_output[n*2+1] = mono_input[n];
  }
  
  return;
}



製品の中には正弦波の他に三角波、矩形波を加える機能をもっているものもあるようです。プログラミングできますので、そのような機能をもたせてみるのも楽しいかもしれません。


■ ビブラートの信号処理

ビブラートはディレイと同じように音を遅延させる処理になります。ただし、その遅延量は、正弦波で与えます。トレモロと異なりエフェクトの効果は抜群でギターの音がシンセのような音に変わります。ただ、演奏するには慣れが必要そうです。

Vibrato.png

dは遅延量を設定するもので、0~2d の間で変化します。ここはサンプルで指定しますが、時間に換算するには、サンプリング周波数の逆数をサンプル数でかけた数になります。正弦波の周波数は小数点以下から数Hzに設定することが多いようです。


■ ビブラートの実装

ビブラートの変数 d には 96サンプル、2ミリ秒の遅延を与えます。音の遅延は0~4ミリ秒で変化します。また、周波数はトレモロと同じく4Hzに設定しました。

#define ARM_MATH_CM4
#define __FPU_PRESENT 1U
#include <cmsis/arm_math.h>

void signal_process(int16_t* mono_input, int16_t* stereo_output, const uint32_t sample_size) {

  /* clean up the output buffer */
  memset(stereo_output, 0, sizeof(int16_t)*sample_size*2);

  /* memory pool for 1.5sec (= 720*100*(1/48000)) */
  static const int lines = 100;
  static int16_t src_buf[SAMPLE_SIZE*lines];  /* 2*720*100=144kBytes */

  /* shift the buffer data in src_buf and add the latest data to top of the bufer */
  memcpy(&src_buf[0], &src_buf[SAMPLE_SIZE], SAMPLE_SIZE*sizeof(int16_t)*(lines-1)); 
  memcpy(&src_buf[(lines-1)*SAMPLE_SIZE], &mono_input[0], SAMPLE_SIZE*sizeof(int16_t));

  const float mod_freq = 4; /* Hz */ 
  const float omega = 2.*PI*mod_freq/AS_SAMPLINGRATE_48000;
  const int sin_total_samples = AS_SAMPLINGRATE_48000/mod_freq;
  const int d = 96; /* delay samples = delay time / Sampling Rate */
  static int theta = 0;

  const int src_buf_end_point = lines*SAMPLE_SIZE-1;
  for (int n = SAMPLE_SIZE-1; n >= 0; --n) {
    float modulation = 1. + arm_sin_f32(omega*theta);
    int offset = (int)(modulation*d);
    mono_input[(SAMPLE_SIZE-1)-n] = src_buf[src_buf_end_point-n-offset];
    if (++theta == sin_total_samples) theta = 0;
  }

  /* copy the signal to output buffer */
  for (int n = SAMPLE_SIZE-1; n >= 0; --n)  {
    stereo_output[n*2] = stereo_output[n*2+1] = mono_input[n];
  }
  
  return;
}



■ コーラスの信号処理

コーラスの信号処理は、ビブラートの変形になります。エコーと同じく遅延した音をもとの音に重ね合わせます。コーラスの効果は、ビブラートのような機械的な音ではなく、自然な音が出せるのでいろいろな場面で使えそうです。

コーラスはその名の通り、声の重ね合わせを表現するので、遅延料 d は数十ミリ秒と比較的大きな値を与え、周波数は小数点以下の値を与えることが多いようです。

Chorus.png



■ コーラスの実装

コーラスの遅延量 d には480サンプル、100ミリ秒を与えます。また周波数は 0.1Hz に設定しました。かなり自然な音に仕上がっていると思います。

#define ARM_MATH_CM4
#define __FPU_PRESENT 1U
#include <cmsis/arm_math.h>

void signal_process(int16_t* mono_input, int16_t* stereo_output, const uint32_t sample_size) {

  /* clean up the output buffer */
  memset(stereo_output, 0, sizeof(int16_t)*sample_size*2);

  /* memory pool for 1.5sec (= 720*100*(1/48000)) */
  static const int lines = 100;
  static int16_t src_buf[SAMPLE_SIZE*lines];  /* 2*720*100=144kBytes */

  /* shift the buffer data in src_buf and add the latest data to top of the bufer */
  memcpy(&src_buf[0], &src_buf[SAMPLE_SIZE], SAMPLE_SIZE*sizeof(int16_t)*(lines-1)); 
  memcpy(&src_buf[(lines-1)*SAMPLE_SIZE], &mono_input[0], SAMPLE_SIZE*sizeof(int16_t));

  const float mod_freq = 0.1; /* Hz */ 
  const float omega = 2.*PI*mod_freq/AS_SAMPLINGRATE_48000;
  const int sin_total_samples = AS_SAMPLINGRATE_48000/mod_freq;
  const int d = 720*2; /* delay samples = 720(samples/frame) * delay time (msec) / 15 (msec/frame) */
  const int p = 480;   /* p must be less than d */
  static int theta = 0;

  const int src_buf_end_point = lines*SAMPLE_SIZE-1;
  for (int n = SAMPLE_SIZE-1; n >= 0; --n) {
    int offset = (int)(d + p*arm_sin_f32(omega*theta));
    mono_input[(SAMPLE_SIZE-1)-n] = (src_buf[src_buf_end_point-n] + src_buf[src_buf_end_point-n-offset])/2;
    if (++theta == sin_total_samples) theta = 0;
  }

  /* copy the signal to output buffer */
  for (int n = SAMPLE_SIZE-1; n >= 0; --n)  {
    stereo_output[n*2] = stereo_output[n*2+1] = mono_input[n];
  }
  
  return;
}




■ 処理の確認

実際の効果を確認してみました。ビブラートの音はかなりエグいですね。SFやホラーの曲で使うと効果がありそうです。プロの演奏を見るとすごく効果的に使っているので関心します。ギターど素人の私には到底ムリなレベル。ペダルでオンオフ、効果の変化を与えられると効果的に使えそうですね。ギター練習しようかな…

今後、簡単に使えるように Arduino のライブラリにまとめていきたいと思います!





「SPRESENSEでデジタルエフェクターを作ろう!」ープリアンプの製作編

「SPRESENSEでデジタルエフェクターを作ろう!」ー低遅延入出力の実現ー

「SPRESENSEでデジタルエフェクターを作ろう!」ーコンプレッサーとディストーションの実現ー

「SPRESENSEでデジタルエフェクターを作ろう!」ー空間系エフェクターの実現ー

「SPRESENSEでデジタルエフェクターを作ろう!」ーモジュレーション系エフェクターの実現ー







SPRESENSEではじめるローパワーエッジAI (Make: PROJECTS)

SPRESENSEではじめるローパワーエッジAI (Make: PROJECTS)

  • 出版社/メーカー: オライリージャパン
  • 発売日: 2022/02/28
  • メディア: 単行本(ソフトカバー)



SONY SPRESENSE メインボード CXD5602PWBMAIN1

SONY SPRESENSE メインボード CXD5602PWBMAIN1

  • 出版社/メーカー: スプレッセンス(Spresense)
  • メディア: Tools & Hardware



SONY SPRESENSE 拡張ボード CXD5602PWBEXT1

SONY SPRESENSE 拡張ボード CXD5602PWBEXT1

  • 出版社/メーカー: スプレッセンス(Spresense)
  • メディア: Tools & Hardware



nice!(20)  コメント(0) 
共通テーマ:趣味・カルチャー