234234234

Nodejs 代码生成一段音频

 

参考:https://www.zhihu.com/question/57929023

 

---

// riffID    4    Chunk ID: RIFF
// cksize    4    Chunk size: 4 + 24 + (8 + M*Nc*Ns + (0 or 1)
// WAVEID    4    WAVE ID: WAVE
// ckID    4    Chunk ID: fmt
// cksize    4    Chunk size: 16
// wFormatTag    2    WAVE_FORMAT_PCM
// nChannels    2    Nc
// nSamplesPerSec    4    F
// nAvgBytesPerSec    4    F*M*Nc
// nBlockAlign    2    M*Nc
// wBitsPerSample    2    rounds up to 8*M
// ckID    4    Chunk ID: data
// cksize    4    Chunk size: M*Nc*Ns
// sampled data    M*Nc*Ns    Nc*Ns channel-interleaved M-byte samples
// pad byte    0 or 1    Padding byte if M*Nc*Ns is odd

const fs = require('fs')

function FormatChunk(channel = 1, frequency = 44100, avgFrequency = 44100) {
    this.fmtID = 'fmt ';
    this.wFormatTag = 0x0001;
    this.nChannels = channel;
    this.nSamplesPerSec = frequency;
    this.nAvgBytesPerSec = avgFrequency * channel;
    this.nBlockAlign = 1;
    this.wBitsPerSample = 8;

    this.bufferSize = 2 + 2 + 4 + 4 + 2 + 2;
    this.getBuffer = () => {
        const buffer = Buffer.alloc(this.bufferSize);
        let oft = 0;
        buffer.writeUInt8(this.wFormatTag, oft);
        oft += 2;
        buffer.writeUInt8(this.nChannels, oft);
        oft += 2;
        buffer.writeUInt32LE(this.nSamplesPerSec, oft);
        oft += 4;
        buffer.writeUInt32LE(this.nAvgBytesPerSec, oft);
        oft += 4;
        buffer.writeUInt8(this.nBlockAlign, oft);
        oft += 2;
        buffer.writeUInt8(this.wBitsPerSample, oft);
        return buffer;
    }
    
}


function Riff() {
    this.riffID = 'RIFF';
}

function SampledData(frequency = 0) {
    this.dataID = "data";
    this.sampled = Buffer.alloc(frequency * 4);
    for (let i = 0; i < frequency * 4; i++) {
        this.sampled.writeUInt8(i % 64 < 32 ? 0 : 255, i);
    }
    this.getBuffer = () => {
        return this.sampled;
    }
    this.bufferSize = frequency * 4;
}


function Wav() {
    this.waveID = 'WAVE';

    this.frequency = 44100;
    this.Nc = 1;
    this.M = 1;
    //三大模块的数据
    this.riff = new Riff();
    this.formatChunk = new FormatChunk(1, this.frequency, this.frequency);
    this.sampledData = new SampledData(this.frequency);

    // 三大模块的字节大小
    this.riffSize  = 4 + 4 + 4 + this.formatChunk.bufferSize + 4 + 4 + this.sampledData.bufferSize;

    // 16 176400 176436
    console.log(this.formatChunk.bufferSize, this.sampledData.bufferSize, this.riffSize);
    // 生成文件二进制
    const fileBufferSize = 4 + 4 + 4 + 4 + 4 + this.formatChunk.bufferSize + 4 + 4 + this.sampledData.bufferSize;
    const fileBuffer = Buffer.alloc(fileBufferSize);
    let fileOft = 0;
    // ----------------
    fileBuffer.write(this.riff.riffID, fileOft);
    fileOft += 4;
    fileBuffer.writeUInt32LE(this.riffSize, fileOft);
    fileOft += 4;
    fileBuffer.write(this.waveID, fileOft);
    fileOft += 4;
    // ----------
    fileBuffer.write(this.formatChunk.fmtID, fileOft);
    fileOft += 4;
    fileBuffer.writeUInt32LE(this.formatChunk.bufferSize, fileOft);
    fileOft += 4;
    // ---------
    // console.log(fileBufferSize);
    const fmtBuffer = this.formatChunk.getBuffer();
    fmtBuffer.copy(fileBuffer, fileOft);
    fileOft += this.formatChunk.bufferSize;
    // -----------
    fileBuffer.write(this.sampledData.dataID, fileOft);
    fileOft += 4;
    fileBuffer.writeUInt32LE(this.sampledData.bufferSize, fileOft);
    fileOft += 4;
    const sampledDataBuffer = this.sampledData.getBuffer();
    sampledDataBuffer.copy(fileBuffer, fileOft);

    return fileBuffer;
}

const fileBuffer = new Wav();

fs.writeFileSync('test.wav', fileBuffer);

 

 

--

posted @ 2022-02-22 09:37  你若愿意,我一定去  阅读(236)  评论(0编辑  收藏  举报
23423423423