java pcm转adpcm_音频编码(PCM,ADPCM,WAVE文件)_烬不需要第四枪的博客-程序员宅基地

技术标签: java pcm转adpcm  

二、给个英文参考网址吧

这两个讲的很详细,请仔细阅读!通过阅读我发现细节在与adpcm格式的wav文件的block的特点,每一个block包含header和data两部分,

Typedef struct{

short  sample0;    //block中第一个采样值(未压缩)

BYTE  index;     //上一个block最后一个index,第一个block的index=0;

BYTE  reserved;   //尚未使用

}MonoBlockHeader

关键是我们要抓住每一个block的header里面的信息,即sample0,运算的时候注意运用!

三、还是给个代码吧,多的也不说了!

1、adpcm.c文件代码

#include"adpcm.h"

/* Intel ADPCM step variation table */

staticintindexTable[16]={

-1,-1,-1,-1,2,4,6,8,

-1,-1,-1,-1,2,4,6,8,

};

staticintstepsizeTable[89]={

7,8,9,10,11,12,13,14,16,17,

19,21,23,25,28,31,34,37,41,45,

50,55,60,66,73,80,88,97,107,118,

130,143,157,173,190,209,230,253,279,307,

337,371,408,449,494,544,598,658,724,796,

876,963,1060,1166,1282,1411,1552,1707,1878,2066,

2272,2499,2749,3024,3327,3660,4026,4428,4871,5358,

5894,6484,7132,7845,8630,9493,10442,11487,12635,13899,

15289,16818,18500,20350,22385,24623,27086,29794,32767

};

voidadpcm_decoder(char*inbuff,char*outbuff,intlen_of_in,structadpcm_state *state )

{

int  i=0,j=0;

chartmp_data;

structadpcm_state *tmp_state =state;

longstep;/* Quantizer step size */

signedlongpredsample;/* Output of ADPCM predictor */

signedlongdiffq;/* Dequantized predicted difference */

intindex;/* Index into step size table */

intSamp;

unsignedcharSampH,SampL;

unsignedcharinCode;

/* Restore previous values of predicted sample and quantizer step

size index

*/

predsample =state->valprev;

index =state->index;

for(i=0;i

{

tmp_data=inbuff[i/2];

if(i%2)

inCode=(tmp_data&0xf0)>>4;

else

inCode=tmp_data &0x0f;

step =stepsizeTable[index];

/* Inverse quantize the ADPCM code into a predicted difference

using the quantizer step size

*/

diffq =step >>3;

if(inCode &4)

diffq +=step;

if(inCode &2)

diffq +=step >>1;

if(inCode &1)

diffq +=step >>2;

/* Fixed predictor computes new predicted sample by adding the

old predicted sample to predicted difference

*/

if(inCode &8)

predsample -=diffq;

else

predsample +=diffq;

/* Check for overflow of the new predicted sample

*/

if(predsample >32767)

predsample =32767;

elseif(predsample 

predsample =-32768;

/* Find new quantizer stepsize index by adding the old index

to a table lookup using the ADPCM code

*/

index +=indexTable[inCode];

/* Check for overflow of the new quantizer step size index

*/

if(index <0)

index =0;

if(index >88)

index =88;

/* Return the new ADPCM code */

Samp=predsample;

if(Samp>=0)

{

SampH=Samp/256;

SampL=Samp-256*SampH;

}

else

{

Samp=32768+Samp;

SampH=Samp/256;

SampL=Samp-256*SampH;

SampH+=0x80;

}

outbuff[j++]=SampL;

outbuff[j++]=SampH;

}

/* Save the predicted sample and quantizer step size index for

next iteration

*/

state->valprev =(short)predsample;

state->index =(char)index;

}

2、adpcm.h文件代码

#ifndefADPCM_H

#defineADPCM_H

#ifdef__cplusplus

extern"C"{

#endif

struct adpcm_state {

short valprev; /* Previous output value */

char index;  /* Index into stepsize table */

};

voidadpcm_decoder(char*inbuff,char*outbuff,intlen_of_in,structadpcm_state *state );

#ifdef__cplusplus

}  /* extern "C" */

#endif

#endif/* ADPCM_H*/

3、main.c文件代码

#include"stdio.h"

#include  "stdlib.h"

#include  "adpcm.h"

#defineCFG_BlkSize     256

charch[CFG_BlkSize];  //用来存储wav文件的头信息

charsavedata[CFG_BlkSize*4];

unsignedcharRiffHeader[]={

'R','I','F','F',// Chunk ID (RIFF)

0x70,0x70,0x70,0x70,// Chunk payload size (calculate after rec!)

'W','A','V','E',// RIFF resource format type

'f','m','t',' ',// Chunk ID (fmt )

0x10,0x00,0x00,0x00,// Chunk payload size (0x14 = 20 bytes)

0x01,0x00,             // Format Tag ()

0x01,0x00,             // Channels (1)

0x40,0x1f,0x00,0x00,// Sample Rate,  = 16.0kHz

0x80,0x3e,0x00,0x00,// Byte rate       32.0K

0x02,0x00,             // BlockAlign == NumChannels * BitsPerSample/8

0x10,0x00     // BitsPerSample

};

unsignedcharRIFFHeader504[]={

'd','a','t','a',// Chunk ID (data)

0x70,0x70,0x70,0x70  // Chunk payload size (calculate after rec!)

};

/****************************************************************

函数名称:    main

功能描述:

输入参数:    none

输出参数:    none

****************************************************************/

voidmain(void)

{

FILE *fpi,*fpo;

unsignedlongiLen,temp;

structadpcm_state ADPCMstate;

unsignedlongi =0;

unsignedlongj;

fpi=fopen("f:\\lk\\test.adpcm","rb");     //为读,打开一个wav文件

if((fpi=fopen("f:\\lk\\test.adpcm","rb"))==NULL)  //若打开文件失败,退出

{

printf("can't open this file\n");

printf("\nread error!\n");

printf("\n%d\n",i);

exit(0);

}

fseek(fpi,0,SEEK_END);

iLen=ftell(fpi);

printf("\n======================================================\n");

printf("\n========================%d========================\n",iLen);

printf("\n======================================================\n");

if((iLen-44)%CFG_BlkSize)

iLen =(iLen-44)/CFG_BlkSize+1;

else

iLen =(iLen-44)/CFG_BlkSize;

fpo=fopen("f:\\lk\\new.pcm","rb+");                     //为写,打开一个wav文件

if((fpo=fopen("f:\\lk\\new.pcm","rb+"))==NULL)          //若打开文件失败,退出

{

printf("can't open this file\n");

printf("\nwrite error!\n");

exit(0);

}

fseek(fpo,0,SEEK_SET);

fwrite(RiffHeader,sizeof(RiffHeader),1,fpo);    //写文件riff

fwrite(RIFFHeader504,sizeof(RIFFHeader504),1,fpo);   //写 data块头

while(i

{

fseek(fpi,48+i*CFG_BlkSize,SEEK_SET);

fread(ch,1,CFG_BlkSize,fpi);

printf("\n======================================================\n");

for(j=0;j<100;j++)

printf("| %d |",ch[j]);

printf("\n======================================================\n");

添加读取BlockHeader部分开始

if(i ==0)

{

ADPCMstate.index =0; //第一个block的index为 0     当前的BlockSize为 256 即采样点数为 (256-4)*2+1 = 505

}

else

{

ADPCMstate.index =ch[2];

}

ADPCMstate.valprev =(short)ch[0]+((short)(ch[1]))*256;   //每一个block里面帧头有一个未压缩的数据 存储时 先低后高

savedata[0]=ch[0];     //存储第一个没有被压缩的数据

savedata[1]=ch[1];     //存储第一个没有被压缩的数据

添加读取BlockHeader部分结束

adpcm_decoder(&ch[4],&savedata[2],CFG_BlkSize-4,&ADPCMstate);//解码出来了   (256-4)*4 个字节

temp =(CFG_BlkSize-4)*4+2;

fseek(fpo,44+i*temp,SEEK_SET);       //开始写声音数据

fwrite(savedata,temp,1,fpo);

i++;

}

temp *=i;

RiffHeader[4]=(unsignedchar)((40+temp)&0x000000ff);

RiffHeader[5]=(unsignedchar)(((40+temp)&0x0000ff00)>>8);

RiffHeader[6]=(unsignedchar)(((40+temp)&0x00ff0000)>>16);

RiffHeader[7]=(unsignedchar)(((40+temp)&0xff000000)>>24);

fseek(fpo,4,SEEK_SET);

fwrite(&RiffHeader[4],4,1,fpo);

RiffHeader[40]=(unsignedchar)(temp&0x000000ff);

RiffHeader[41]=(unsignedchar)((temp&0x0000ff00)>>8);

RiffHeader[42]=(unsignedchar)((temp&0x00ff0000)>>16);

RiffHeader[43]=(unsignedchar)((temp&0xff000000)>>24);

fseek(fpo,40,SEEK_SET);

fwrite(&RiffHeader[40],4,1,fpo);

fclose(fpi);

fclose(fpo);

printf("\n==========================OK!=========================\n");

}

四、以上是给出的代码,绝对管用,读者在实验时候请在vc++6.0环境下建立工程,实验时候请在f:\\lk\\下放置一个adpcm格式的文件和一个空的pcm格式文件,当然了这个pcm和adpcm其实都是wav格式的,试验者可以随意命名格式,我为了区分才这样命名后缀的,希望我总结的能够读者带来帮助,谢谢您的阅读!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42355003/article/details/114202862

智能推荐

ONLINE DDL INPLACE和COPY两种方式MDL锁的区别-程序员宅基地

MySQL online DDL分为INPLACE和COPY两种方式,通过在ALTER语句的ALGORITHM参数指定,两种方式除了实现方式不同外,整个过程中MDL上锁也是不一样的。对于alter table test...._online ddl inplace

Using Headless Mode in the Java SE Platform--转-程序员宅基地

原文地址:By Artem Ananiev and Alla Redko, June 2006 Articles IndexThis article explains how to use the headless mode capabilities of the Java Platform, Standard Ed..._using_headless

富瀚MC6630移植并安装GDB调试工具_富瀚调试工具csdn_I&You的博客-程序员宅基地

富瀚MC6630移植并安装GDB下载gdb所需的源文件-------------"点这里"解压并安装ncurses-5.9解压并安装expat_2.0.1.orig解压并安装gdb-7.6在板端配置环境cp gdb命令cp 所需的lib板端挂载nfs,并配置gdb命令和lib的环境大功告成下载gdb所需的源文件-------------“点这里”解压并安装ncurses-5.91. cd ncurses-5.6 //进入解压后目录2. /configure --host=arm-mol-linux-_富瀚调试工具csdn

【19调剂】武汉大学计算机学院2019年硕士研究生复试调剂录取工作实施细则(院内)...-程序员宅基地

点击文末的阅读原文或者公众号界面左下角的调剂信息或者公众号回复“调剂”是计算机/软件等专业的所有调剂信息集合,会一直更新的。四、调剂政策(一)全日制学硕接收院内全日制学硕调剂。考生可申请...

通过webservice实现天气预报-程序员宅基地

1. WebServices简介1.1什么是WebServices WebServices是应用程序组件 WebServices使用开放协议进行通信 WebServices是独立并可以自我描述 WebServices可通过使用UDDI来发现 WebServices可被其它应用程序使用 XML是WebServices的基础1.2...

使用doxygen查看文件包含关系图-程序员宅基地

http://blog.sina.com.cn/s/blog_4b976b2d0100jk0b.html转载于:https://www.cnblogs.com/hengli/archive/2013/01/22/2870888.html_doxygen 类图包含组合关系

随便推点

虚拟机、主机和开发板三者互ping相通_虚拟机开发板主机-程序员宅基地

比较心碎的感觉,本来开发板挂载虚拟机中的文件系统一直都是工作正常的,不知道怎么了,今天却是怎么都挂载不成功,浪费了快两个小时才搞定,最后发现是个很逗比的问题,可能是最近修改了一个网络配置文件让我的虚拟机可以上网导致把我的auto eth3变成了ifupidown eth3 且不能进行编辑,何等杯具,目前个人认为就因为这个原因导致的挂载不成功!现在就跟大家分享如何KIll了这个ifupido_虚拟机开发板主机

​win10下安装 RabbitMQ​_win10 rabbitmq connection network_柚几哥哥的博客-程序员宅基地

RabbitMQ 下载地址 https://www.rabbitmq.com/install-windows.html 安装需要注意要以管理员权限下载安装包,然后就是傻瓜式安装下一步下一步就行,如果大家自定义安装路径的话,一定要保证你的安装路径没有中文,没有空格,然后等待两个都安装成功后,我们需要配置下 Erlang 的环境变量 7、首先可以在 RabbitMQ 的目录下执行 rabbitmqctl status 查看当前服务是否启动,也可以在win10的服务页面来查看 RabbitMQ 服务是否启_win10 rabbitmq connection network

packet_write_wait:Connection to xxx.xxx.xxx.xxx port 2220 Broken pipe错误处理_ssh登录报错:packet_write_wait: connection to x.x.x.x p-程序员宅基地

1,在~/.ssh/config配置文件中添加 IPQoS lowdelay throughput2,在/etc/ssh/ssh_config配置文件中添加 IPQoS lowdelay throughput_ssh登录报错:packet_write_wait: connection to x.x.x.x port 22: broken pip

Netty学习前置知识(一)_netty的前置知识-程序员宅基地

文章目录前言Netty 介绍Netty 使用场景互联网行业游戏行业大数据领域Java IO模型IO模型BIO,NIO,AIO场景分析比较Java BIO 编程Java BIO介绍Java BIO工作机制BIO工作机制梳理Java BIO编程实例问题分析Java NIO 编程Java NIO介绍NIO 与 BIO比较NIO三大核心原理图NIO 的 Selector、Channel 和、Buffer 之间关系三大核心关系解读缓冲区Buffer基本介绍Buffer及其子类基本属性: capacity, limit_netty的前置知识

解放双手,声音编程是一种什么体验?_serenade中文 写代码_iFlyAI的博客-程序员宅基地

在开始学习之前推荐大家可以多在FlyAI竞赛服务平台多参加训练和竞赛,以此来提升自己的能力。FlyAI是为AI开发者提供数据竞赛并支持GPU离线训练的一站式服务平台。每周免费提供项目开源算法样例,支持算法能力变现以及快速的迭代算法模型。“加个Hello函数”“加个Print”“在Hello中加引号”……程序员们,以后不要轻易动手了,声音编程了解一下~现在就有一款免费的AI小工具Serenade,插入正在使用的编译器(如VS Code、IntelliJ、Ato..._serenade中文 写代码

sed命令中关于-n的使用_为什么sed s不能加 -n-程序员宅基地

-n参数的作用是抑制自动输出首先看下一文件data内容执行sed 's/dog/cat/p' data命令查看效果执行sed -n 's/dog/cat/p' data命令效果再看一组命令对比sed '2s/dog/cat/p' data和sed -n '2s/dog/cat/p' data命令运行效果如下:..._为什么sed s不能加 -n

推荐文章

热门文章

相关标签