Annotation of nono/host/sounddriver_wav.cpp, revision 1.1.1.2

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2025 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // サウンドの Wav ドライバ
                      9: //
                     10: 
                     11: #include "sounddriver_wav.h"
                     12: #include "mainapp.h"
                     13: #include <time.h>
                     14: 
                     15: // コンストラクタ
                     16: SoundDriverWav::SoundDriverWav(HostDevice *hostdev_)
                     17:        : inherited(hostdev_, "wav")
                     18: {
                     19: }
                     20: 
                     21: // デストラクタ
                     22: SoundDriverWav::~SoundDriverWav()
                     23: {
                     24:        CloseWav();
                     25: }
                     26: 
                     27: bool
                     28: SoundDriverWav::InitDriver(bool startup)
                     29: {
                     30:        if (inherited::InitDriver(startup) == false) {
                     31:                return false;
                     32:        }
                     33: 
                     34:        le16buf.resize(blkbytes / sizeof(int16));
                     35: 
                     36:        return true;
                     37: }
                     38: 
                     39: // ブロック書き出し
                     40: void
                     41: SoundDriverWav::Write(const int16 *blk)
                     42: {
                     43:        if (__predict_false(fp == NULL)) {
                     44:                if (OpenWav() == false) {
                     45:                        return;
                     46:                }
                     47:        }
                     48: 
                     49:        // データはホストエンディアンなので LE16 にして末尾に追加。
                     50:        // LE 環境では無駄だが、LE は大抵速いのと #if になるほうが嫌なので。
                     51:        for (uint i = 0, end = le16buf.size(); i < end; i++) {
                     52:                le16buf[i] = htole16(blk[i]);
                     53:        }
                     54:        fwrite(le16buf.data(), sizeof(int16), le16buf.size(), fp);
                     55: 
                     56:        databytes += blkbytes;
                     57: 
                     58:        // データ長に関連するフィールドを更新。
                     59:        // +$04 に (ファイルサイズ - 8) で、
                     60:        // これはこのフィールド以降のデータ長なので
                     61:        // データ開始位置までの 0x24 バイト分とデータ長の和。
                     62:        fseek(fp, 0x04, SEEK_SET);
                     63:        fwrite4LE(fp, databytes + 0x24);
                     64: 
                     65:        // +$28 にデータ長。
                     66:        fseek(fp, 0x28, SEEK_SET);
                     67:        fwrite4LE(fp, databytes);
                     68: 
                     69:        // ポジションを末尾に戻しておく。
                     70:        fseek(fp, 0, SEEK_END);
                     71: }
                     72: 
                     73: bool
                     74: SoundDriverWav::OpenWav()
                     75: {
                     76:        struct timespec ts;
                     77:        char namebuf[32];
                     78:        struct tm tmbuf;
                     79: 
                     80:        // 現在時刻からファイル名を作る。
                     81:        clock_gettime(CLOCK_REALTIME, &ts);
                     82:        localtime_r(&ts.tv_sec, &tmbuf);
                     83:        strftime(namebuf, sizeof(namebuf), "%Y%m%d-%H%M%S.wav", &tmbuf);
                     84:        filename = std::string(namebuf);
                     85:        std::string pathname = gMainApp.GetVMDir() + "/" + filename;
                     86: 
                     87:        fp = fopen(pathname.c_str(), "w");
                     88:        if (fp == NULL) {
                     89:                return false;
                     90:        }
                     91: 
                     92:        // ヘッダを出力。
                     93:        fwrite(wav_header, 1, sizeof(wav_header), fp);
                     94: 
                     95:        // +$18 にサンプリング周波数。
                     96:        fseek(fp, 0x18L, SEEK_SET);
                     97:        fwrite4LE(fp, freq);
                     98: 
                     99:        // +$1c に 1秒あたりのバイト数。
                    100:        fwrite4LE(fp, freq * 4);
                    101: 
                    102:        // ポジションを末尾に戻しておく。
                    103:        fseek(fp, 0, SEEK_END);
                    104: 
                    105:        databytes = 0;
                    106: 
                    107:        return true;
                    108: }
                    109: 
                    110: // fp の指定の現在位置から val を LE32 で書き込む。
                    111: void
                    112: SoundDriverWav::fwrite4LE(FILE *fp_, uint32 val)
                    113: {
                    114:        uint32 data = htole32(val);
                    115:        fwrite(&data, sizeof(data), 1, fp_);
                    116: }
                    117: 
                    118: // WAV ファイルを閉じる。(何度呼び出しても副作用はない)
                    119: void
                    120: SoundDriverWav::CloseWav()
                    121: {
                    122:        if (fp) {
                    123:                fclose(fp);
                    124:                fp = NULL;
                    125:        }
                    126: }
                    127: 
                    128: void
1.1.1.2 ! root      129: SoundDriverWav::MonitorScreenMD(TextScreen& screen, int y)
1.1       root      130: {
                    131:        screen.Print(0, y, "Filename: %s", filename.c_str());
                    132: }
                    133: 
                    134: /*static*/ const uint8
                    135: SoundDriverWav::wav_header[0x2c] = {
                    136:        'R', 'I', 'F', 'F',                     // +$00
                    137:        0, 0, 0, 0,                                     // +$04: ここに、(ファイルサイズ - 8)
                    138:        'W', 'A', 'V', 'E',                     // +$08: フォーマット
                    139: 
                    140:        'f', 'm', 't', ' ',                     // +$0c: fmt チャンク識別子
                    141:        16, 0, 0, 0,                            // +$10: 以降のチャンクサイズ
                    142:        1, 0,                                           // +$14: フォーマット種別(1=リニアPCM)
                    143:        2, 0,                                           // +$16: チャンネル数
                    144:        0, 0, 0, 0,                                     // +$18: サンプリング周波数 [Hz]
                    145:        0, 0, 0, 0,                                     // +$1c: 1秒あたりのバイト数
                    146:        4, 0,                                           // +$20: こっちでいうフレームサイズ
                    147:        16, 0,                                          // +$22: ビット/サンプル
                    148: 
                    149:        'd', 'a', 't', 'a',                     // +$24: data チャンク識別子
                    150:        0, 0, 0, 0,                                     // +$28: ここに、以降のチャンクサイズ
                    151:                                                                // +$2c: ここからデータ
                    152: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.