簡體   English   中英

將 CELT 音頻解碼為 WAV

[英]Decoded CELT audio to WAV

我需要從 CS:GO 游戲服務器中提取語音數據。 引擎給了我壓縮音頻片段 stream,然后我通過 celt 庫 (IVoiceCodec::Decompress) 解壓縮,就像在這個源代碼中所做的一樣: https://github.com/perilouswithadollarsign/cstrike15_src/blob/f82112a2388b841d72cb612ca46fcc188 /engine/audio/private/voice.cpp

該接口沒有提供任何有關解碼數據的信息,但從源代碼中我可以猜測它應該是單通道 16bit/22050KHz PCM 音頻

static std::vector<char> buffer;

char decompressedData[MAX_UNCOMPRESSED_VOICE_BUFFER_SIZE];  
const int decompressedBytes = g_pCodec->Decompress(data.data(),
                                                   data.size(),
                                                   decompressedData,
                                                   MAX_UNCOMPRESSED_VOICE_BUFFER_SIZE);

if(decompressedBytes > 0)
    buffer.insert(buffer.end(),
                  decompressedData,
                  decompressedData + decompressedBytes);
        
if(buffer.size() > 50000)
{
    static int fileIndex = 0;
    const std::string fileName("wav/test_" + std::to_string(clientIndex) + "_" + std::to_string(fileIndex) + ".wav");
    const bool result = WriteWaveFile(fileName.c_str(),
                    buffer.data(),
                    buffer.size(),
                    16, // Bits per sample
                    1, // Channels
                    22050 // Samples per sec
                    );
                    
    buffer.clear();
        
    ++fileIndex;
}

解碼器工作時沒有錯誤並輸出正確的數據(解碼后我可以辨認出聲音)。 然后我將這些片段保存為單通道 16 位/22050KHz PCM WAV 文件而沒有任何更改。 從技術上講,我在數據前添加了 42 個字節的 WAV header。 然后我合並文件。 這是我得到的示例: https://drive.google.com/file/d/16iSC-GXzzl5wwYsvAQN1Hkk93LuSyRYG/view?usp=share_link音調聽起來正確,但播放速度太快,我能聽到噪音。

這是我編寫wav文件的代碼(我也是從引擎源代碼中得到的):

void WriteDWord(FileHandle_t fp, unsigned long val) 
{
    g_pFileSystem->Write(&val, 4, fp);
}

void WriteWord(FileHandle_t fp, unsigned short val) 
{
    g_pFileSystem->Write(&val, 2, fp);
}

bool WriteWaveFile(
    const char *pFilename, 
    const char *pData, 
    int nBytes, 
    int wBitsPerSample, 
    int nChannels, 
    int nSamplesPerSec)
{
    FileHandle_t fp = g_pFileSystem->Open(pFilename, "wb");
    if(!fp)
        return false;

    // Write the RIFF chunk.
    g_pFileSystem->Write("RIFF", 4, fp);
    WriteDWord(fp, 0);
    g_pFileSystem->Write("WAVE", 4, fp);


    // Write the FORMAT chunk.
    g_pFileSystem->Write("fmt ", 4, fp);

    WriteDWord(fp, 0x10);
    WriteWord(fp, WAVE_FORMAT_PCM);
    WriteWord(fp, (unsigned short)nChannels);   
    WriteDWord(fp, (unsigned long)nSamplesPerSec);
    WriteDWord(fp, (unsigned long)((wBitsPerSample / 8) * nChannels * nSamplesPerSec));
    WriteWord(fp, (unsigned short)((wBitsPerSample / 8) * nChannels));
    WriteWord(fp, (unsigned long)wBitsPerSample);

    // Write the DATA chunk.
    g_pFileSystem->Write("data", 4, fp);
    WriteDWord(fp, (unsigned long)nBytes);
    g_pFileSystem->Write(pData, nBytes, fp);

    // Go back and write the length of the riff file.
    unsigned long dwVal = g_pFileSystem->Tell(fp) - 8;
    g_pFileSystem->Seek(fp, 4, FILESYSTEM_SEEK_HEAD);
    WriteDWord(fp, dwVal);

    g_pFileSystem->Close(fp);
    return true;
}

我嘗試更改采樣率和每個樣本的位數,但仍然得到錯誤的結果。 wav 文件有什么問題?

IVoiceCodec::Decompress 似乎返回樣本數而不是寫入的字節數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM