Hope is a Dream. Dream is a Hope.

非公開ブログは再開しました。

C/C++で音声出力

最近C#を使って音声処理系のアプリケーションが書けるようになったが、 実はwindowsの音声出力が良く分からない

そこらへんは便利なラッパーライブラリを使って見ないフリをしていた

改めてC/C++でwin32apiから勉強してみる

参考ページ

C言語/C++ - Sample is best! - アットウィキ

C言語/C++/wave - Sample is best! - アットウィキ

C++によるオーディオ信号処理(1) ---環境構築とサンプルプログラム動作確認--- : 工作と競馬

#pragma comment(lib, "winmm.lib")

#define _USE_MATH_DEFINES

#include <math.h>
#include <stdio.h>
#include <Windows.h>

#include <locale.h> // LC_CTYPE
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>

#define VOLUME 64
#define FREQ   440
#define SAMPLE_RATE    11025
#define TONE_MSEC  1000
#define DATA_LEN   (SAMPLE_RATE * TONE_MSEC / 1000)

int main() {
    WAVEFORMATEX    waveformatx;
    MMRESULT        mmresult;
    HWAVEOUT        handle_wave_out;
    WAVEHDR         wave_header;

    char           acData[DATA_LEN]; // MAX 256 (8bit = 1Byte)
    double         dWave;
    int                i;

    // 波形データの生成 Generate Waveform
    for (i = 0; i < DATA_LEN; i++) {
        dWave = sin(i * FREQ * 2 * M_PI / SAMPLE_RATE);
        acData[i] = (char)(dWave * VOLUME) + 128;
        //acData[i] = rand() * 2 * VOLUME / RAND_MAX + 128 - VOLUME; // ホワイトノイズ

    }

    // Play
    waveformatx.wFormatTag = WAVE_FORMAT_PCM;
    waveformatx.nChannels = 1;
    waveformatx.nSamplesPerSec = SAMPLE_RATE;
    waveformatx.nAvgBytesPerSec = SAMPLE_RATE;
    waveformatx.nBlockAlign = 1;
    waveformatx.wBitsPerSample = 8; // 8bit
    waveformatx.cbSize = 0;

    const UINT device_nomber = waveOutGetNumDevs();
    printf("Device no : %d\n", device_nomber);

    // USER Inputs
    printf("Please Input Device ID\n");

    UINT deviceid = 0;
    scanf_s("%d", &deviceid);
    printf("%d\n", deviceid);

    // Check Device Open
    mmresult = waveOutOpen(&handle_wave_out, deviceid, &waveformatx, 0, 0, CALLBACK_NULL);

    if (mmresult != MMSYSERR_NOERROR) {

        printf("error: waveOutOpen\n");

        switch (mmresult)
        {
        case  MMSYSERR_ALLOCATED:
            printf("error: MMSYSERR_ALLOCATED\n");
            break;
        case  MMSYSERR_BADDEVICEID:
            printf("error: MMSYSERR_BADDEVICEID\n");
            break;
        case  MMSYSERR_NODRIVER:
            printf("error: MMSYSERR_NODRIVER\n");
            break;
        case  MMSYSERR_NOMEM:
            printf("error: MMSYSERR_NOMEM\n");
            break;
        case  WAVERR_BADFORMAT:
            printf("error: WAVERR_BADFORMAT\n");
            break;
        case  WAVERR_SYNC:
            printf("error: WAVERR_SYNC\n");
            break;
        default:
            break;
        }

        system("pause");
        return 1;
    }


    // waveOutPrepareHeader
    ZeroMemory(&wave_header, sizeof wave_header);

    wave_header.lpData = acData;
    wave_header.dwBufferLength = DATA_LEN;

    mmresult = waveOutPrepareHeader(handle_wave_out, &wave_header, sizeof wave_header);

    if (mmresult != MMSYSERR_NOERROR) {

        fprintf(stderr, "error: waveOutPrepareHeader\n");

        switch (mmresult)
        {
        case  MMSYSERR_INVALHANDLE:
            printf("error: MMSYSERR_INVALHANDLE\n");
            break;
        case  MMSYSERR_NODRIVER:
            printf("error: MMSYSERR_NODRIVER\n");
            break;
        case  MMSYSERR_NOMEM:
            printf("error: MMSYSERR_NOMEM\n");
            break;
        default:
            break;
        }

        system("pause");
        return 1;
    }

    // waveOutWrite
    mmresult = waveOutWrite(handle_wave_out, &wave_header, sizeof wave_header);
    if (mmresult != MMSYSERR_NOERROR) {

        fprintf(stderr, "error: waveOutWrite\n");

        switch (mmresult)
        {
        case  MMSYSERR_INVALHANDLE:
            printf("error: MMSYSERR_INVALHANDLE\n");
            break;
        case  MMSYSERR_NODRIVER:
            printf("error: MMSYSERR_NODRIVER\n");
            break;
        case  MMSYSERR_NOMEM:
            printf("error: MMSYSERR_NOMEM\n");
            break;
        default:
            break;
        }

        system("pause");

        return 1;
    }

    // wait
    Sleep(TONE_MSEC);

    // Stop

    // waveOutReset
    mmresult = waveOutReset(handle_wave_out);
    if (mmresult != MMSYSERR_NOERROR) {
        fprintf(stderr, "error: waveOutReset\n");
        switch (mmresult)
        {
        case  MMSYSERR_INVALHANDLE:
            printf("error: MMSYSERR_INVALHANDLE\n");
            break;
        case  MMSYSERR_NODRIVER:
            printf("error: MMSYSERR_NODRIVER\n");
            break;
        case  MMSYSERR_NOMEM:
            printf("error: MMSYSERR_NOMEM\n");
            break;
        case  MMSYSERR_NOTSUPPORTED:
            printf("error: MMSYSERR_NOTSUPPORTED\n");
            break;
        default:
            break;
        }
        system("pause");

        return 1;
    }

    // waveOutUnprepareHeader
    mmresult = waveOutUnprepareHeader(handle_wave_out, &wave_header, sizeof wave_header);
    if (mmresult != MMSYSERR_NOERROR) {

        fprintf(stderr, "error: waveOutUnprepareHeader\n");

        switch (mmresult)
        {
        case  MMSYSERR_INVALHANDLE:
            printf("error: MMSYSERR_INVALHANDLE\n");
            break;
        case  MMSYSERR_NODRIVER:
            printf("error: MMSYSERR_NODRIVER\n");
            break;
        case  MMSYSERR_NOMEM:
            printf("error: MMSYSERR_NOMEM\n");
            break;
        case  MMSYSERR_NOTSUPPORTED:
            printf("error: MMSYSERR_NOTSUPPORTED\n");
            break;
        default:
            break;
        }
        system("pause");

        return 1;
    }

    // waveOutClose
    mmresult = waveOutClose(handle_wave_out);
    if (mmresult != MMSYSERR_NOERROR) {

        fprintf(stderr, "error: waveOutClose\n");

        switch (mmresult)
        {
        case  MMSYSERR_INVALHANDLE:
            printf("error: MMSYSERR_INVALHANDLE\n");
            break;
        case  MMSYSERR_NODRIVER:
            printf("error: MMSYSERR_NODRIVER\n");
            break;
        case  MMSYSERR_NOMEM:
            printf("error: MMSYSERR_NOMEM\n");
            break;
        case  WAVERR_STILLPLAYING:
            printf("error: WAVERR_STILLPLAYING\n");
            break;
        default:
            break;
        }

        system("pause");

        return 1;
    }



    system("pause");
    return 0;
}

いやーややこしい。

改訂新版 C/C++によるディジタル信号処理入門 (ディジタル信号処理シリーズ)

改訂新版 C/C++によるディジタル信号処理入門 (ディジタル信号処理シリーズ)

スピーカエンクロージャー製作 その1

 

スピーカを作る

 

スピーカエンクロージャを作る

 

 

とあるイベント用にスピーカ製作の依頼を受けました。

 

2wayのスピーカを4セット分を一つのオブジェクトにまとめる仕様ということで。

イベント自体は8/19とまだ一ヶ月あるのですが、スピーカ駆動用のアンプや、マイク入力+ボイスエフェクト等の回路もオーダーで受けているのでそれぞれの準備を一月前から始めようと思っています

 

## 依頼内容

+ スピーカ x 8発 (+ ネットワーク)

+ アンプ 各100W程度

+ マイクアンプ

+ マイクエフェクター(ディストーション)

+ 電源回路

 

## スピーカ エージング用エンクロージャ製作

 

せっかくですのでスピーカのエージングもかねてエンクロージャーを設計します.

目的は8発スピーカのエージングと、ネットワークの音質セッティング、木材加工の外注も初めてなので試しでもあります。

 

木材加工・販売は、DIY 日曜大工応援隊!

 

イメージは以下のようになりました。

 

f:id:hope_is_dream:20180716114707j:image

 

4面全てに2Wayスピーカを配置します.

あまり何も考えずに箱を作るように、板をはめ合う場合は、板厚の分シンメトリーになりません。ただ、せっかくなので4面シンメトリーにしたかったので、顔面の両端に板厚と等しい太さの支柱を設けてシンメトリにしました。材質変えて色を変える予定です。

 

### スピーカユニット

コイズミ無線を除くとちょうど2Wayのセット販売をしていましたのでそれを採用します。

メインのユニットはできるだけ大きい方が男らしいのですが、製作物の都合もあり16cmとしておきます。まぁワンルームの中でみるとソコソコ存在感あります。

プラスツイータのセットで15千円程度でした。(ネッワーク用コイル、コンデンサ)もこみです

 

2wayシステムキット|コイズミ無線

16cmウーファー2Wayセット(ペア) 2WSET1602-2 - コイズミ無線NET

 

### エンクロージャ設計

 

Fusion360を使って設計します。まずは地道にスピーカを作って生きます

 

 

#### Faital Pro 16cm 定価 5,934円(内税)

 

まずはFaital Pro 16cmから。

コイズミ無線は図面等が準備されていてとても親切です。

 

dp00000116.shop-pro.jp

 

 

f:id:hope_is_dream:20180716171419p:plain

 

せっせと作りました

ほとんどは断面でスケッチ描いて回転させての繰り返しです。

大事なのはネジ穴の位置と、開口径なので細かい部分は適当です。

今回の場合は狭いエンクロージャに閉じ込めるので、ボイスコイル同士が干渉する事態がおきました。ので、ボイスコイルの寸法はきっちりとします。

 

f:id:hope_is_dream:20180716171926p:plain

 

2D図面化したのはこちら。

 

f:id:hope_is_dream:20180716174102p:plain

 

 

### HiVi ドームツイーター K1 定価 2,031円(内税)

  

dp00000116.shop-pro.jp

 

 

結構それっぽく出来たと思います。いい感じ。

 

f:id:hope_is_dream:20180716174400p:plain

 

 

f:id:hope_is_dream:20180716174530p:plain

 

次回はエンクロージャー部分を作ります

 

 

 

 

TEDxTitech 聴講

 

f:id:hope_is_dream:20180513185314p:image

 

 

こんにちはフィフィです。

 

今日は東工大にTEDxを聴講しに行ってきました。

 

f:id:hope_is_dream:20180513184756j:image

 

TEDxTitech 2018

 

TEDはランチ後のお昼寝の前によく見させて貰っていましたが、参加は初めて。

 

やっぱり映像とは全然違いました。

生の声から受けるパッションと緊張はYoutubeではまだ代替できないみたいです。

 

テーマは学際。複数の学術分野にまたがるテーマの追求。

例えば、メディカルイラストレーター = 医学 + アート

tokco - MEMBERS ~ LAIMAN | サイエンス&メディカルイラストレーションの株式会社レーマン

 

例えば、ギャル電 = ギャル + Lチカ以上Iot未満

ギャル電 (@GALDEN999) on Twitter

 

などなど

 

多種のスピーカーが参加されとても有意義な時間でした。

 

vivaldiのエンジニアも講演されていました。

Vivaldiは公開当初から応援していることもあり大変刺激になりました。

Vivaldi Browser | Fast & Flexible Web Browser

 

宣伝しておきますので皆さん一度ダウンロードを

f:id:hope_is_dream:20180513191053j:image

 

 

ご観覧ありがとうございました。

 

フィ