MCUの DAC( Digital to Analog Converter )を使用して発声を行う機能です。発声は 音声合成ライブラリを使用しています。
◀ この記事の前に: Voice driver( 操作説明 )
▶ この記事の次に: 音声合成ライブラリ
- 概 要
- モジュールの構造
- 関数の概要
- 外部関数
- 内部関数
- ライブラリ関数( I2S ライブラリ )
- i2s_driver_install( i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue )
- i2s_set_adc_mode( adc_unit_t adc_unit, adc1_channel_t adc_channel )
- i2s_zero_dma_buffer( i2s_port_t i2s_num )
- i2s_write( i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait )
- i2s_driver_uninstall( i2s_port_t i2s_num )
- ライブラリ関数( 音声合成ライブラリ )
- データの構造
- コード
- 外部関数
- 内部関数
- 参考情報
概 要
発音を行う処理です。音声合成ライブラリと I2Sを使用して DAC出力を行います。省電力制御も連動します。
モジュールの構造
発音はローマ字表記に近い音声記号列で表した発音データから、音声合成ライブラリにより発音を行います。音声合成ライブラリは音声波形データを作ります。音声波形データは DACによりアナログ信号に変換して出力します。DACは I2Sライブラリで操作します。DAC出力は MCU外部の DAC増幅回路の入力となりスピーカーを鳴らします。
DAC増幅回路の電源は ON/OFF制御することができます。上位には Speak interpreterがあり統合的にアプリケーションから操作することができます。Voice driver 単独でも操作することができます。音声合成ライブラリに関しては以下をご覧ください。
関数の概要
関数は以下のとおりです。
外部関数
他のジュールやファイルの外部からアクセス可能な関数です。
setPowerControVD( int nSwitchPower )
引 数:
・DAC 増幅回路の電源の操作( nSwitchPower ):
SOUND_POWER_ON : DAC 増幅回路の電源 ON
SOUND_POWER_OFF: DAC 増幅回路の電源 OFF
分 類:
API( 省電力制御、 対象は Speak Interpreter、他 )
機 能:
DAC 増幅回路の電源を ON / OFF する。
関係する関数:
上位関数: operateSI()、アプリケーション、他
下位関数: ー
この関数のコードはこちらです。
playVD( const char szData )
引 数:
・const char szData: 発音するローマ字表記音声記号列( ASCII )
ローマ字表記音声記号列( ASCII )の詳細は以下をご覧ください。
・ローマ字音声記号列仕様書: 発音のデータ(文字列)の仕様書 / 株式会社 アクエスト
分 類:
API( 対象は Speak Interpreter、他 )
機 能:
発音処理の本体。AquesTalk Pi ライブラリと I2S ライブラリを使用して引数の音声( 音声記号列 )を発音する。
注 意
- 発声開始前に createDAC_VD() が、発声終了後に releaseDAC_VD() の実行が必要です。
- 発声開始前に setPowerControVD( VOICE_ON )が、発声終了後に setPowerControVD( VOICE_OFF ) の実行が必要です。発声開始前に DAC出力増幅回路が OFFの場合、誤動作( 不意なリセット等 )が発生する場合があります。
関係する関数:
上位関数: playSI()、speakSI()、アプリケーション、他
下位関数: CAqTkPicoF_SetKoe()、CAqTkPicoF_SyntheFrame()、writeDAC_VD()
この関数のコードはこちらです。
setSpeedVD( int nInput )
引 数:
・String szInput: 設定する発音速度 [%] を 50 ~ 300の間で指定する。( 初期値は 100 )
分 類:
API( 対象は Speak Interpreter、他 )
機 能:
発声速度を設定(変更)する。
関係する関数:
上位関数: setSpeedSI()、アプリケーション、他
下位関数: ( CAqTkPicoF_SetKoe() )
この関数のコードはこちらです。
createDAC_VD()
引 数:
なし
分 類:
API( 対象は Speak Interpreter、他 )
機 能:
発音処理の準備を行う。
関係する関数:
上位関数: operateSI()、アプリケーション、他
下位関数: AqResample_Reset()、i2s_driver_install()、i2s_set_dac_mode()、i2s_zero_dma_buffer()
この関数のコードはこちらです。
releaseDAC_VD()
引 数:
なし
分 類:
API( 対象は Speak Interpreter、他 )
機 能:
発音処理の終結を行う。
関係する関数:
上位関数: operateSI()、アプリケーション、他
下位関数: i2s_driver_uninstall()
この関数のコードはこちらです。
内部関数
setupVD()
引 数:
なし
分 類:
内部関数( 初期化 )
機 能:
音声合成ライブラリの初期化を行います。
関係する関数:
上位関数: setup()
下位関数: CAqTkPicoF_Init()
この関数のコードはこちらです。
writeDAC_VD( int len, int16_t *wav )
引 数:
・int len: 波形データのデータ長
・int16_t *wav: 波形データ
戻り値:
・int : エラー値( -1:ESP_FAIL / 0:TIMEOUT )
分 類:
内部関数( 初期化 )
機 能:
発音を行います。
関係する関数:
上位関数: playVD()
下位関数: AqResample_Conv()
この関数のコードはこちら#code_writeDAC_VDです。
ライブラリ関数( I2S ライブラリ )
I2Sライブラリ内の関数です。
詳細は以下をご覧ください。
・M5StickC非公式日本語リファレンス( i2s ) /
・m5stack/M5StickC / M5Stack Quick & easy IoT development
関数の説明は上記の仕様書からの抜粋です。
戻り値の esp_err_t は、ESP32のESP-IDF( Espressif IoT Development Framework )で使用されるエラーコードの型です。
i2s_driver_install( i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue )
引 数:
・i2s_port_t i2s_num: DMAバッファの指定( I2S_NUM_0、I2S_NUM_1 )
・i2s_config_tconst *i2s_configI2S: I2S のコンフィグレーションを参照
・int queue_sizeI2S: イベント キューのサイズ/深さ。
・void *i2s_queueI2S: イベント キュー ハンドル。NULL に設定するとドライバはイベント キューを使用しない。
戻り値:
esp_err_t
分 類:
内部関数( I2Sライブラリ )
機 能:
I2S ドライバーをインストールして起動する。
関係する関数:
上位関数: createDAC_VD()
下位関数: ー
i2s_set_adc_mode( adc_unit_t adc_unit, adc1_channel_t adc_channel )
引 数:
・adc_unit_t adc_unit: SAR ADC ユニットの番号
・adc1_channel_t *i2s_configI2Sadc_channel: ADC チャネルの番号
戻り値:
esp_err_t
分 類:
内部関数( I2Sライブラリ )
機 能:
I2S DMA の組み込み ADC モードを設定する。
関係する関数:
上位関数: createDAC_VD()
下位関数: ー
i2s_zero_dma_buffer( i2s_port_t i2s_num )
引 数:
・i2s_port_t i2s_num: DMAバッファの指定( I2S_NUM_0、I2S_NUM_1 )
戻り値:
esp_err_t
分 類:
内部関数( I2Sライブラリ )
機 能:
TX DMA バッファの内容をゼロにする。
関係する関数:
上位関数: createDAC_VD()
下位関数: ー
i2s_write( i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait )
引 数:
・i2s_port_t i2s_num: DMAバッファの指定( I2S_NUM_0、I2S_NUM_1 )
・const void *src: 書き込み元のデータの所在アドレス
・size_t size: データのサイズ( バイト単位 )
・size_t *bytes_written: 書き込まれたバイト数
・TickType_t ticks_to_wait: TX バッファ待機タイムアウト ( RTOS ティック単位 )
戻り値:
esp_err_t
分 類:
内部関数( I2Sライブラリ )
機 能:
I2S DMA 送信バッファにデータを書き込む。
関係する関数:
上位関数: playVD()
下位関数: ー
i2s_driver_uninstall( i2s_port_t i2s_num )
引 数:
・i2s_port_t i2s_num: DMAバッファの指定( I2S_NUM_0、I2S_NUM_1 )
戻り値:
esp_err_t
分 類:
内部関数( I2Sライブラリ )
機 能:
I2S ドライバーをアンインストールする。
関係する関数:
上位関数: releaseDAC_VD()
下位関数: ー
ライブラリ関数( 音声合成ライブラリ )
音声合成ライブラリ( AquesTalk-ESP32 Ver.2.0 )内の関数です。
詳細は以下をご覧ください。
・テキスト音声合成ライブラリ 「AquesTalk pico」 標準インターフェース仕様書(フレーム合成版)
/ 株式会社アクエスト
関数の説明は上記の仕様書からの抜粋です。
CAqTkPicoF_Init( uint32_t *buf, uint16_t lenFrame )
引 数:
・buf: ワークバッファのアドレスを指定。バッファのサイズはAQ_SIZE_WORKBUF(AqTkPicoF.h 内に規定)
音声合成が終了するまで、解放や内容の書き換えは不可。
・lenFrame: フレーム長(1度のSyntheFrame()呼び出しで生成するサンプル数)を30-320の間で指定。 デフォルト:160
戻り値:
uint8_t
0:正常終了 0以外:エラー
分 類:
音声合成ライブラリ
機 能:
音声合成ライブラリの初期化処理です。
関係する関数:
上位関数: setupVD()
下位関数: -
CAqTkPicoF_SetKoe( const uint8_t *koe, uint16_t speed, uint16_t lenPause )
引 数:
・koe: 音声記号列( 1文程度を指定 )を指定( 文字列の先頭アドレス。NULL終端 )
・speed: 発話速度の指定。 値を大きく設定するほど、速くなる。発話速度 [%] 50-300 の間で指定。デフォルト:100
・lenPause: 最後のポーズ( 無音区間 )の長さを指定。 0xffffU を指定すると、内部の標準ポーズ長。 最後のポーズが不要な場合は、256の指定を推薦。
戻り値:
uint8_t
0:正常終了 0以外:エラー
分 類:
音声合成ライブラリ
機 能:
音声記号列をライブラリに設定します。
関係する関数:
上位関数: playVD()
下位関数: -
CAqTkPicoF_SyntheFrame( short *wav, uint16_t *pLen )
引 数:
・wav: 音声波形出力バッファ。生成した1フレームの音声波形データがここに書き込まれて戻る。 バッファのサイズはlenFrameで指定した値以上とし、外部で確保する。
・pLen: 生成したデータのサンプル数を返す。通常、最終フレーム以外はlenFrameで指定した値。 最終フレームはlenFrame以下になる。
戻り値:
uint8_t
0:正常終了 0以外:End of Data それ以外:エラー
最終フレームも0を返す。その次に呼び出したときに1を返す。
分 類:
音声合成ライブラリ
機 能:
音声波形を1フレーム生成 CAqTkPicoF_SetKoe()でセットした音声記号列から、音声を1フレーム生成して戻る。 (1フレームの長さは CAqTkPicoF_Init() で先に指定)
関係する関数:
上位関数: playVD()
下位関数: -
AqResample_Conv( short *wav, uint16_t *pLen )
引 数:
・wav: 音声波形出力バッファ。生成した1フレームの音声波形データがここに書き込まれて戻る。 バッファのサイズはlenFrameで指定した値以上とし、外部で確保する。
・pLen: 生成したデータのサンプル数を返す。通常、最終フレーム以外はlenFrameで指定した値。 最終フレームはlenFrame以下になる。
戻り値:
uint8_t
0:正常終了 0以外:End of Data それ以外:エラー
最終フレームも0を返す。その次に呼び出したときに1を返す。
分 類:
音声合成ライブラリ
機 能:
アップサンプリングするためにサンプリング周波数を変換する。
関係する関数:
上位関数: writeDAC_VD()
下位関数: -
Technical Considerations アップサンプリング
アップサンプリング( Upsampling / オーバーサンプリングとも呼ばれる )はデータセット内のデータの数を増やして、データの不均衡を修正するデータ処理の手法です。オーディオの世界では、アップサンプリングは音質向上や DACの最適化 などの目的で行われます。
AqResample_Reset()
引 数:
なし
戻り値:
uint8_t
0:正常終了 0以外:End of Data それ以外:エラー
最終フレームも0を返す。その次に呼び出したときに1を返す。
分 類:
音声合成ライブラリ
機 能:
アップサンプリング処理の初期化
関係する関数:
上位関数: createDAC_VD()
下位関数: -
データの構造
データの構造は以下のとおりです。
グローバル定義
グローバル定義は以下のとおりです。
//------------------------------------------------------------------------------
// IO pin name definition
//------------------------------------------------------------------------------
//-----------------------------------------------
// IO pin list
//-----------------------------------------------
...
//---- Voice / DAC / AMP ----
#define PIN_DAC 25 // DAC output
#define PIN_PS_AMP 26 // Amplifier power saving control
//------------------------------------------------------------------------------
// Voice driver
//------------------------------------------------------------------------------
//---- Power saving control ----
//.... Output logic ....
#define AMP_POWER_ON HIGH // power saving control for DAC amplifier
#define AMP_POWER_OFF LOW
//.... Argument ....
#define SOUND_POWER_ON 1 //
#define SOUND_POWER_OFF 0
//---- Voice data ----
#define VD_BUF_LEN 32 //
#define VD_DMA_BUFNO 0 // i2s port number
名 称 | 型 | 値 | 説 明 |
---|---|---|---|
PIN_DAC | define | 25 | DAC 出力の信号ピン |
PIN_PS_AMP | define | 26 | DAC 増幅回路の省電力制御用の信号ピン |
AMP_POWER_ON | define | HIGH | DAC 増幅回路の電源 ON時の出力 |
AMP_POWER_OFF | define | LOW | DAC 増幅回路の電源 OFF時の出力 |
SOUND_POWER_ON | define | 1 | DAC 増幅回路の電源 ON |
SOUND_POWER_OFF | define | 0 | DAC 増幅回路の電源 OFF |
VD_BUF_LEN | define | 32 | 発音波形データの生成時のサンプル数 |
VD_DMA_BUFNO | define | 0 | 使用する DMAのバッファ指定 |
FLASHメモリ内の定義
FLASHメモリ内の定義です。
要 素 | 設定値 | 説 明 |
---|---|---|
AQUEST_LICENSE_KEY | – | 音声合成ライブラリのライセンスキー |
I2S のコンフィグレーション
I2Sのコンフィグレーションに関する定義です。
//.... i2s configuration ....
i2s_config_t i2s_config = {
// Master and transmit mode
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
// Sampling rate 12kHz
.sample_rate = 12000,
// 16bit Audio
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
// Stereo
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
// I2S Format MSB first
.communication_format = (i2s_comm_format_t)I2S_COMM_FORMAT_I2S_MSB,
// Deault interrupt
.intr_alloc_flags = 0,
// Number of DMA buffer
.dma_buf_count = 4,
// Length of DMA buffer
.dma_buf_len = 384,
// No useed Audio PLL
.use_apll = false,
// Enabled automatic clear
.tx_desc_auto_clear = true,
// Setting automatic for Master clock
.fixed_mclk = 0
};
要 素 | 設定値 / 説明 | |
---|---|---|
.mode | (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN) | |
マスター + 送信モード | ||
.sample_rate | 12000 | |
サンプリングレート: 12kHz | ||
.bits_per_sample | I2S_BITS_PER_SAMPLE_16BIT | |
16ビットオーディオ | ||
.channel_format | I2S_CHANNEL_FMT_RIGHT_LEFT | |
ステレオ | ||
.communication_format | (i2s_comm_format_t)I2S_COMM_FORMAT_I2S_MSB | |
I2Sの通信フォーマットMSBファースト | ||
.intr_alloc_flags | 0 | デフォルトの割り込み設定 |
.dma_buf_count | 4 | DMAバッファ数 |
.dma_buf_len | 384 | 1つのDMAバッファの長さ |
.use_apll | 0 | APLL (オーディオPLL) を使用しない |
.tx_desc_auto_clear | true | 自動クリアを有効化 |
.fixed_mclk | 0 | 固定のマスタークロックは自動設定 |
音声合成ライブラリ内の定義
音声合成ライブラリ( AquesTalk-ESP32 Ver.2.0 )を使用するときのインクルードファイル内での定義です。
要 素 | 初期値 | 説 明 |
---|---|---|
AQ_SIZE_WORKBUF | 100 | x4byte、ローマ字音声記号列から生成した音声波形データのバッファ長 |
グローバル変数
グローバル変数は以下のとおりです。
//==============================================================================
// Variable definitions in source code
//==============================================================================
//------------------------------------------------------------------------------
// Voice driver
//------------------------------------------------------------------------------
//.... control ....
bool gVDenable = SOUND_POWER_OFF; // amplifier power saving control
int gVDspeed = 100; // speaking speed
int gVDvolume = 100; // speaking volume
//.... buffer ....
uint32_t gVDbuffer[ AQ_SIZE_WORKBUF ];
要 素 | 型 | 初期値 | 説 明 |
---|---|---|---|
gVDenable | bool | false | 発音処理の ON/OFF状態の保存 ・ON: True ・OFF: False |
gVDspeed | int | 100 | 発音速度 [%] を 50 ~ 300の間で指定 |
gVDvolume | int | 100 | 発音音量 [%] を 0 ~ 100の間で指定 |
gVDbuffer[AQ_SIZE_WORKBUF] | uint32_t | 0 | 発音波形データのバッファ |
コード
コードは以下のとおりです。
インクルードファイル
必要なインクルードファイルは以下のとおりです。
要 素 | 説 明 |
---|---|
“driver/i2s.h” | I2S の使用 |
“aquestalk.h” | 音声合成ライブラリ( AquesTalk-ESP32 Ver.2.0 )の使用 |
関数間の関係
処理ごとの関数の関係は以下のとおりです。

関数の関係は以下のとおりです。
外部関数
setPowerControVD( int nSwitchPower )
DAC 増幅回路の電源を ON / OFF します。
/*----------------------------------------------------------------------------*/
/* Power saving control for DAC amplifier
/* param : int nSwitch / control amplifier power saving
/* return : -
/*----------------------------------------------------------------------------*/
setPowerControVD( int nSwitch )
{
if( nSwitch == VOICE_ON ){
gVDenable = true;
digitalWrite( PIN_PS_AMP, AMP_POWER_ON );
} else {
gVDenable = false;
digitalWrite( PIN_PS_AMP, AMP_POWER_OFF );
}
}
playVD( String szSpeakData )
発音処理の本体。AquesTalk Pi ライブラリと I2S ライブラリを使用して引数の音声( 音声記号列 )を発音します。
注 意
- 発声開始前に createDAC_VD() が、発声終了後に releaseDAC_VD() の実行が必要です。
- 発声開始前に setPowerControVD( VOICE_ON )が、発声終了後に setPowerControVD( VOICE_OFF ) の実行が必要です。発声開始前に DAC出力増幅回路が OFFの場合、誤動作( 不意なリセット等 )が発生する場合があります。
/*----------------------------------------------------------------------------*/
/* Playback phonetic symbol data
/* param : String szSpeakData / AquesTalk phonetic symbol data
/* return : -
/*----------------------------------------------------------------------------*/
void PlayVD( String szSpeakData )
{
//.... local ....
int nRet;
char koe[ LEN_SI_PHRASE ];
int16_t wav[ VD_BUF_LEN ];
uint16_t len;
if( gVDenable == false ){
return;
}
//.... set phrase data to Voice Library ....
szSpeakData.toCharArray( koe, sizeof(koe) );
CAqTkPicoF_SetKoe( (const uint8_t*)koe, gVDspeed, 0xffffU );
for (;;) {
//.... synthesis voice wave data from Voice Library ....
nRet = CAqTkPicoF_SyntheFrame( wav, &len );
if ( nRet ) {
break; // EOD
}
//.... send to DAC ....
writeDAC_VD( (int)len, wav ) ;
}
i2s_zero_dma_buffer( (i2s_port_t)VD_DMA_BUFNO );
}
発音する文章( 音声記号列 )を事前に設定する CAqTkPicoF_SetKoe()を実行し、フレーム長ごとに設定した文章( 音声記号列 )を CAqTkPicoF_SyntheFrame()を実行して波形データに変換します。( WAV[] )変換処理は1フレームごとに行います。フレーム長を VD_BUF_LEN( = 32 サンプル )に指定しましたので、32 / 8kHz( 4 ms )ごとに音声を生成します。波形データは writeDAC_VD()を介して DAC出力します。
すべての発生後に i2s_zero_dma_buffer()を実行して DMAバッファをクリアにします。
setSpeedVD( int nSpeed )
発声速度の設定を行います。
/*----------------------------------------------------------------------------*/
/* Set speaking speed
/* param : int nSpeed / speaking speed
/* return : -
/*----------------------------------------------------------------------------*/
void setSpeedVD( int nSpeed )
{
nSpeed = gVDspeed;
}
発声速度は CAqTkPicoF_SetKoe()の引数で設定しています。発生時に gVDspeedを使用することにより発声速度が決まります。
createDAC_VD()
発音処理の準備を行う。
/*----------------------------------------------------------------------------*/
/* Setup DAC
/* param : -
/* return : -
/*----------------------------------------------------------------------------*/
void createDAC_VD()
{
AqResample_Reset();
i2s_driver_install( (i2s_port_t)VD_DMA_BUFNO, &i2s_config, 0, NULL );
i2s_set_dac_mode( I2S_DAC_CHANNEL_RIGHT_EN ); // 25
i2s_zero_dma_buffer( (i2s_port_t)VD_DMA_BUFNO );
}
アップサンプリング処理の初期化 AqResample_Reset() と I2Sの初期化を行います。初期化パラメータは I2S のコンフィグレーションで設定しています。
出力ピン GPIO と DAC出力の左右の対応は以下のとおりです。
・RIGHT: IO25( Qumcum Lab. は IO25をモノラルの DAC出力としています。 )
・LEFT: IO26( DAC出力の増幅回路の省電力制御に使用しています。 )
releaseDAC_VD()
発音処理の終結を行う。
/*----------------------------------------------------------------------------*/
/* Release DAC
/* param : -
/* return : -
/*----------------------------------------------------------------------------*/
void releaseDAC_VD()
{
i2s_driver_uninstall( (i2s_port_t)VD_DMA_BUFNO );
}
I2S ドライバをアンインストールします。
内部関数
setup() 内
音声合成ライブラリの初期化処理を呼び出します。
void setup( void )
{
・・・
/* Initialize Voice driver */
setupVD(); // include DAC initialize
・・・
}
setupVD()
音声合成ライブラリの初期化と DAC増幅回路を OFFにします。
/*----------------------------------------------------------------------------*/
/* Initialize Voice driver
/* param : -
/* return : -
/*----------------------------------------------------------------------------*/
void setupVoice()
{
CAqTkPicoF_Init( gVDbuffer, VD_BUF_LEN, AQUEST_LICENSE_KEY ); //●●○
setPowerControVD( SOUND_POWER_OFF );
}
writeDAC_VD()
発音を行う。
/*----------------------------------------------------------------------------*/
/* Write DAC data
/* param : int len / length of wavedata
/* int16_t *wav / wavedata
/* return : int /
/*----------------------------------------------------------------------------*/
int writeDAC_VD( int len, int16_t *wav )
{
//.... local ....
int i, k, nRet;
int16_t wav3[3];
uint16_t us;
uint16_t sample[2];
size_t transBytes;
for ( i = 0; i < len; i++ ) {
//.... upsampling x3 ....
AqResample_Conv( wav[i], wav3 );
//.... write to I2S DMA buffer ....
for ( k = 0; k < 3; k++ ) {
us = ( (uint16_t)wav3[k] ) ^ 0x8000U;
sample[0] = sample[1] = us; // mono -> stereo
nRet = i2s_write( (i2s_port_t)VD_DMA_BUFNO, (const char*)sample, 4, &transBytes, portMAX_DELAY );
if ( nRet < 0 ) {
return nRet; // -1:ESP_FAIL
}
if ( nRet == 0 ) {
break; // 0:TIMEOUT
}
}
}
return nRet;
}
データの流れを中心にした処理の手順は以下のとおりです。
発声速度は CAqTkPicoF_SetKoe()の引数で設定しています。発生時に gVDspeedを使用することにより発声速度が決まります。AqResample_Conv()によりアップサンプリングして雑音を抑えています。( 3倍
I2Sのデータは符号付きで 16bitデータの場合、値は-32768~32767の範囲( 中央値は0 )です。ESP32の DACは、0-65535( 下位8bitは無視 )の範囲であり中央値が 32768になります。そのための変換を行っています。( 外部 DACを使うときは変換はしません。 )
I2Sのクロックレート
クロックレートの決め方です。
ESP32のI2S設定で、i2s_config_t.sample_rate( サンプリングレート )と I2S_CHANNEL_MONO( モノラル設定 )には 密接な関係 があります。ESP32のI2Sは、ステレオ( 左右2ch ) と モノラル( 1ch ) の2種類のデータフォーマットをサポートしています。以下のとおりです。
- モノラル( 1ch ): I2S_CHANNEL_MONO = 1
- ステレオ( 2ch ): I2S_CHANNEL_STEREO = 2
ESP32のI2Sハードウェアでは、データの送信・受信は常に「左チャンネル + 右チャンネル」の単位 で処理されます。モノラル設定の場合も、内部的にはステレオデータとして処理 されます。
I2S_CHANNEL_MONO を設定しても、ESP32のI2Sは 内部的にはステレオデータのクロックを使います。そのため、モノラルのサンプルレートを設定すると、実際にはその 2倍のクロックが必要 になります。
AquesTalkは、WAV フォーマット( 8KHz サンプリング、16bitPCM、モノラル )データです。但し、24KHzサンプリングにアップサンプリング機能を含んでいます。
サンプルプログラムはステレオで処理しています。また3倍のアップサンプリングを行っています。そのため 8kHz X 3 = 24 kHzとなりますが、ステレオ処理のため 1/2 の 12000( 12kHz )がサンプリング周波数となります。
モノラルで処理する場合( I2S_CHANNEL_MONO )は、1/1のため 24000( 24kHz )のサンプリング周波数となります。
参考情報
参考になる情報は以下のとおりです。
このホームページ内
- 発音・発声( DAC出力 / ハードウエア ): MCUの DACを使用して発音や発声を行うハードウエアを説明します。
- Speak interpreter ( 概要 ): 発声処理の最上位、Speak interrupter の概要です。
- Speak interpreter( 操作説明 ): アプリケーションからの操作方法です。( API )
- Speak interpreter( コード ): コードの詳細を説明します。
- Voice driver( 概要 ): 発音そのものの処理です。( API )
- Voice driver( 操作説明 ): 個々のサーボモータを制御する方法です。
- Voice driver( コード ): コードの詳細を説明します。
- 音声合成ライブラリ: ライブラリの概要や導入方法を説明します。
他のWebサイト
- M5StickC非公式日本語リファレンス( i2s ): I2Sの内部関数に関する詳しい説明
- 「アップサンプリング」で音は良くなる? 変わらない? 独自手法を提案する技術者に聞く: 藤本健のDigital Audio Laboratory
- ESP32でI2S+DACを使う: I2Sで内蔵 DACを使用する概要 / Qiita.成松 宏