From 3354160ab5d31b915ec550e6506eb76d998e0fee Mon Sep 17 00:00:00 2001 From: dezhihuang Date: Sun, 12 Nov 2017 17:06:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86PCM16LE=E5=8F=8C=E5=A3=B0=E9=81=93?= =?UTF-8?q?=E9=9F=B3=E9=A2=91=E9=87=87=E6=A0=B7=E6=95=B0=E6=8D=AE=E4=B8=AD?= =?UTF-8?q?=E5=B7=A6=E5=A3=B0=E9=81=93=E7=9A=84=E9=9F=B3=E9=87=8F=E9=99=8D?= =?UTF-8?q?=E4=B8=80=E5=8D=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 67 ++++++++++++++++++++++++++++++++++++++ pcm16le_halfvolumeleft.cpp | 63 +++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 pcm16le_halfvolumeleft.cpp diff --git a/README.md b/README.md index e1c19ea..cde76d9 100644 --- a/README.md +++ b/README.md @@ -390,9 +390,76 @@ output_r.pcm:右声道数据。
+## 将PCM16LE双声道音频采样数据中左声道的音量降一半 +> 注:本文中声音样值的采样频率一律是44100Hz,采样格式一律为16LE。“16”代表采样位数是16bit。由于1Byte=8bit,所以一个声道的一个采样值占用2Byte。“LE”代表Little Endian,代表2 Byte采样值的存储方式为高位存在高地址中。 +``` C++ +// +//本程序中的函数可以将PCM16LE双声道数据中左声道的音量降低一半。 +// +#include +#include +#include +int pcm16le_halfvolumeleft(const char *file) +{ + if (file == NULL) { + printf("原始文件为空!\n"); + return 0; + } + + FILE *fp = fopen(file, "rb+"); + if (fp == NULL) { + printf("原始文件打开失败!\n"); + return 0; + } + + FILE *fp1 = fopen("./output/output_halfleft.pcm", "wb+"); + if (fp1 == NULL) { + printf("文件打开或创建失败!\n"); + return 0; + } + + unsigned char buf[4] = {0}; + + while(!feof(fp)) { + //从文件中读取一次采样值,因为是16位的,所以需读取4个字节 + //左右声道采样值间隔存储 + //前两个字节为左声道采样值,后两个字节为右声道采样值 + fread(buf, 1, 4, fp); + + //将前两个字节(左声道采样值)强制转换为 short类型 + short *sample = (short *)buf; + + //将左声道采样值减半 + *sample = *sample / 2; + + //将减半的左声道采样值写入文件 + fwrite(sample, 1, 2, fp1); + + //将原始的右声道采样值写入文件 + fwrite(buf+2, 1, 2, fp1); + } + + fclose(fp); + fclose(fp1); + + return 1; +} + +int main() +{ + char file[] = "./mediadata/NocturneNo2inEflat_44.1k_s16le.pcm"; + if (pcm16le_halfvolumeleft(file)) { + printf("操作成功!!!\n"); + } else { + printf("操作失败!!!\n"); + } +} +``` + +从源代码可以看出,本程序在读出左声道的2 Byte的取样值之后,将其当成了C语言中的一个short类型的变量。将该数值除以2之后写回到了PCM文件中。 diff --git a/pcm16le_halfvolumeleft.cpp b/pcm16le_halfvolumeleft.cpp new file mode 100644 index 0000000..1c1020e --- /dev/null +++ b/pcm16le_halfvolumeleft.cpp @@ -0,0 +1,63 @@ +// +//本程序中的函数可以将PCM16LE双声道数据中左声道的音量降低一半。 +// + +#include +#include +#include + +int pcm16le_halfvolumeleft(const char *file) +{ + if (file == NULL) { + printf("原始文件为空!\n"); + return 0; + } + + FILE *fp = fopen(file, "rb+"); + if (fp == NULL) { + printf("原始文件打开失败!\n"); + return 0; + } + + FILE *fp1 = fopen("./output/output_halfleft.pcm", "wb+"); + if (fp1 == NULL) { + printf("文件打开或创建失败!\n"); + return 0; + } + + unsigned char buf[4] = {0}; + + while(!feof(fp)) { + //从文件中读取一次采样值,因为是16位的,所以需读取4个字节 + //左右声道采样值间隔存储 + //前两个字节为左声道采样值,后两个字节为右声道采样值 + fread(buf, 1, 4, fp); + + //将前两个字节(左声道采样值)强制转换为 short类型 + short *sample = (short *)buf; + + //将左声道采样值减半 + *sample = *sample / 2; + + //将减半的左声道采样值写入文件 + fwrite(sample, 1, 2, fp1); + + //将原始的右声道采样值写入文件 + fwrite(buf+2, 1, 2, fp1); + } + + fclose(fp); + fclose(fp1); + + return 1; +} + +int main() +{ + char file[] = "./mediadata/NocturneNo2inEflat_44.1k_s16le.pcm"; + if (pcm16le_halfvolumeleft(file)) { + printf("操作成功!!!\n"); + } else { + printf("操作失败!!!\n"); + } +} \ No newline at end of file