最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++將音頻PCM數(shù)據(jù)封裝成wav文件的方法

 更新時間:2022年01月13日 13:31:36   作者:Alfred-N  
這篇文章主要為大家詳細介紹了C++將音頻PCM數(shù)據(jù)封裝成wav文件的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

前言

使用聲音設(shè)備采集的聲音數(shù)據(jù)通常是PCM數(shù)據(jù),直接寫入文件是無法播放的,通常的做法是將其封裝成wav格式,這樣播放器就能夠識別且播放了。本文將介紹如何將PCM封裝成wav的方法。

一、如何實現(xiàn)?

首先需要構(gòu)造wav頭部,wav文件音頻信息全部保存在頭部,我們要做的就是在PCM數(shù)據(jù)的前面加入wav頭,并且記錄PCM的相關(guān)參數(shù)。

1.定義頭結(jié)構(gòu)

只定義PCM格式的wav文件頭

//WAV頭部結(jié)構(gòu)-PCM格式
struct WavPCMFileHeader;

2.預留頭部空間

創(chuàng)建文件時預留頭部空間

FILE*f = fopen(fileName.c_str(), "wb+");
//預留頭部位置
fseek(f, sizeof(WavPCMFileHeader), SEEK_SET);

3.寫入PCM數(shù)據(jù)

寫入數(shù)據(jù),并記錄數(shù)據(jù)總長度。

fwrite(data, 1, dataLength, f);
//錄數(shù)據(jù)總長度
_totalDataLength += dataLength;

4.寫入頭部信息

關(guān)閉文件時,回到起始位置寫入頭部信息

//寫入頭部信息
fseek(f, 0, SEEK_SET);
WavPCMFileHeader h(_channels, _sampleRate, _bitsPerSample, _totalDataLength);
fwrite(&h, 1, sizeof(h), f);
fclose(f);

二、完整代碼

WavWapper.h

#pragma once
#include<string>
namespace AC {
?? ?class ?WavWapper {
?? ?public:
?? ??? ?WavWapper();
?? ??? ?~WavWapper();
?? ??? ?/// <summary>
?? ??? ?/// 創(chuàng)建wav文件
?? ??? ?/// </summary>
?? ??? ?/// <param name="fileName">文件名</param>
?? ??? ?/// <param name="channels">聲道數(shù)</param>
?? ??? ?/// <param name="sampleRate">采樣率,單位hz</param>
?? ??? ?/// <param name="bitsPerSample">位深</param>
?? ??? ?void CreateWavFile(const std::string &fileName, int channels, int ?sampleRate, int ?bitsPerSample);
?? ??? ?/// <summary>
?? ??? ?/// 寫入PCM數(shù)據(jù)
?? ??? ?/// </summary>
?? ??? ?/// <param name="data">PCM數(shù)據(jù)</param>
?? ??? ?/// <param name="dataLength">數(shù)據(jù)長度</param>
?? ??? ?void WriteToFile(unsigned char* data, int dataLength);
?? ??? ?/// <summary>
?? ??? ?/// 關(guān)閉文件
?? ??? ?/// </summary>
?? ??? ?void CloseFile();
?? ?private:
?? ??? ?void* _file=nullptr;
?? ??? ?uint32_t _totalDataLength=0;
?? ?};
}

WavWapper.cpp

#include"WavWapper.h"
#include<stdio.h>
namespace AC {
?? ?//WAV頭部結(jié)構(gòu)-PCM格式
?? ?struct WavPCMFileHeader
?? ?{
?? ??? ?struct RIFF {
?? ??? ??? ?const?? ?char rift[4] = { 'R','I', 'F', 'F' };
?? ??? ??? ?uint32_t fileLength;
?? ??? ??? ?const?? ?char wave[4] = { 'W','A', 'V', 'E' };
?? ??? ?}riff;
?? ??? ?struct Format
?? ??? ?{
?? ??? ??? ?const?? ?char fmt[4] = { 'f','m', 't', ' ' };
?? ??? ??? ?uint32_t blockSize = 16;
?? ??? ??? ?uint16_t formatTag;
?? ??? ??? ?uint16_t channels;
?? ??? ??? ?uint32_t samplesPerSec;
?? ??? ??? ?uint32_t avgBytesPerSec;
?? ??? ??? ?uint16_t blockAlign;
?? ??? ??? ?uint16_t ?bitsPerSample;
?? ??? ?}format;
?? ??? ?struct ?Data
?? ??? ?{
?? ??? ??? ?const?? ?char data[4] = { 'd','a', 't', 'a' };
?? ??? ??? ?uint32_t dataLength;
?? ??? ?}data;
?? ??? ?WavPCMFileHeader() {}
?? ??? ?WavPCMFileHeader(int nCh, int ?nSampleRate, int ?bitsPerSample, int dataSize) {
?? ??? ??? ?riff.fileLength = 36 + dataSize;
?? ??? ??? ?format.formatTag = 1;
?? ??? ??? ?format.channels = nCh;
?? ??? ??? ?format.samplesPerSec = nSampleRate;
?? ??? ??? ?format.avgBytesPerSec = nSampleRate * nCh * bitsPerSample / 8;
?? ??? ??? ?format.blockAlign = nCh * bitsPerSample / 8;
?? ??? ??? ?format.bitsPerSample = bitsPerSample;
?? ??? ??? ?data.dataLength = dataSize;
?? ??? ?}
?? ?};
?? ?WavWapper::WavWapper()
?? ?{
?? ?}

?? ?WavWapper::~WavWapper()
?? ?{
?? ??? ?CloseFile();
?? ?}
?? ?int _channels;
?? ?int _sampleRate;
?? ?int _bitsPerSample;
?? ?void WavWapper::CreateWavFile(const std::string& fileName, int channels, int sampleRate, int bitsPerSample)
?? ?{
?? ??? ?if (!_file)
?? ??? ?{
?? ??? ??? ?_channels = channels;
?? ??? ??? ?_sampleRate = sampleRate;
?? ??? ??? ?_bitsPerSample = bitsPerSample;
?? ??? ??? ?_totalDataLength = 0;
?? ??? ??? ?_file = fopen(fileName.c_str(), "wb+");
?? ??? ??? ?//預留頭部位置
?? ??? ??? ?fseek(static_cast<FILE*>(_file), sizeof(WavPCMFileHeader), SEEK_SET);
?? ??? ?}
?? ?}
?? ?void WavWapper::WriteToFile(unsigned char* data, int dataLength)
?? ?{
?? ??? ?fwrite(data, 1, dataLength, static_cast<FILE*>(_file));
?? ??? ?_totalDataLength += dataLength;
?? ?}
?? ?void WavWapper::CloseFile()
?? ?{
?? ??? ?if (_file)
?? ??? ?{
?? ??? ??? ?if (_totalDataLength > 0)
?? ??? ??? ?{
?? ??? ??? ??? ?//寫入頭部信息
?? ??? ??? ??? ?fseek(static_cast<FILE*>(_file), 0, SEEK_SET);
?? ??? ??? ??? ?WavPCMFileHeader h(_channels, _sampleRate, _bitsPerSample, _totalDataLength);
?? ??? ??? ??? ?fwrite(&h, 1, sizeof(h), static_cast<FILE*>(_file));
?? ??? ??? ?}
?? ??? ??? ?fclose(static_cast<FILE*>(_file));
?? ??? ??? ?_file = nullptr;
?? ??? ?}
?? ?}
}

三、使用示例

#include "WavWapper.h"
#include<Windows.h>
int main()
{?? ?
?? ?AC::WavWapper ww;
?? ?//創(chuàng)建wav文件,確保pcm聲音格式與參數(shù)一致
?? ?ww.CreateWavFile("sound.wav",2, 44100, 16);
?? ?while (flag)
?? ?{
?? ??? ?//獲取PCM數(shù)據(jù)
?? ??? ?//略
?? ??? ?//獲取PCM數(shù)據(jù)-end
?? ? ? ?//寫入PCM數(shù)據(jù)
?? ??? ?ww.WriteToFile(data, dataLength);
?? ?}
?? ?//關(guān)閉文件
?? ?ww.CloseFile();?? ?
}

總結(jié)

以上就是今天要講的內(nèi)容,PCM封裝成wav還是相對較簡單的,只要了解wav頭結(jié)構(gòu),然后自定義其頭結(jié)構(gòu),然后再進行一定的測試,就可以實現(xiàn)這樣一個功能。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C語言深入講解函數(shù)的使用

    C語言深入講解函數(shù)的使用

    各位小伙伴們,今天YU同學給大家?guī)淼氖桥c函數(shù)相關(guān)的知識,本篇將會帶著大家初步認識和調(diào)用函數(shù)來解決一些簡單的問題
    2022-04-04
  • C++中Copy-Swap實現(xiàn)拷貝交換

    C++中Copy-Swap實現(xiàn)拷貝交換

    本文主要介紹了C++中Copy-Swap實現(xiàn)拷貝交換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • C++17?Filesystem?實用教程

    C++17?Filesystem?實用教程

    C++17的std::filesystem庫提供了強大的文件系統(tǒng)操作工具,本文就來介紹一下C++17?Filesystem?實用教程,具有一定的參考價值,感興趣的可以了解一下
    2025-01-01
  • dev?c++的使用和調(diào)試方式

    dev?c++的使用和調(diào)試方式

    這篇文章主要介紹了dev?c++?的使用和調(diào)試方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • C語言逆向分析語法超詳細分析

    C語言逆向分析語法超詳細分析

    這篇文章主要介紹了C語言逆向分析語法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-11-11
  • C++破壞MBR的代碼

    C++破壞MBR的代碼

    這篇文章主要介紹了C++破壞MBR的代碼,涉及到對硬盤的主引導記錄的破壞性操作,具有一定的參考價值,需要的朋友可以參考下
    2014-10-10
  • C++ namespace案例詳解

    C++ namespace案例詳解

    這篇文章主要介紹了C++ namespace案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C語言實現(xiàn)全排列算法模板的方法

    C語言實現(xiàn)全排列算法模板的方法

    這篇文章主要介紹了C語言實現(xiàn)全排列算法模板的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • C語言指針與引用的區(qū)別以及引用的三種用法案例詳解

    C語言指針與引用的區(qū)別以及引用的三種用法案例詳解

    這篇文章主要介紹了C語言指針與引用的區(qū)別以及引用的三種用法案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • OpenCV實現(xiàn)區(qū)域分割和區(qū)域生長

    OpenCV實現(xiàn)區(qū)域分割和區(qū)域生長

    區(qū)域分割是圖像處理中一個重要的任務(wù),本文主要介紹了OpenCV實現(xiàn)區(qū)域分割和區(qū)域生長,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-02-02

最新評論

安乡县| 思茅市| 枝江市| 佛坪县| 景宁| 木兰县| 镶黄旗| 新野县| 商都县| 西乌| 江北区| 永新县| 聂拉木县| 宜兴市| 姚安县| 密山市| 汤原县| 陆河县| 威宁| 六安市| 江安县| 靖边县| 阿克| 文化| 湘潭市| 灵山县| 新乡县| 景洪市| 天峻县| 托里县| 天水市| 娱乐| 新营市| 铜川市| 道孚县| 繁峙县| 安泽县| 临武县| 广灵县| 象州县| 孙吴县|