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

智能推荐

蓝牙解码格式哪个最好_柏韵Pureaudio AirDSD Pro 串流播放解码前级-程序员宅基地

柏韵Pureaudio AirDSD Pro audio streaming Pre-amp串流播放解码前级类“牛入牛出” 模拟输入 前级 DSD24.5M PCM768KHz DXD 352.8kHz SACD iso DSDDop 数播 DAC解码 无线WiFi音频 流媒体 DLNA 蓝牙BT5.0Air..._蓝牙解码格式哪个最好

5-vue-template模板制作_mao_mao37的博客-程序员宅基地

有四种方法制作模板,下边先将前三种制作模板。注意:模板组件里面第一行只能有一个标签,并且结束标签必须在最后一行,否则结束标签之后的html是无法显示的;一:直接在构造器中制作模板,构造器模板 <script> new Vue({ el:'#ele', data:{ mes...

python置换加密解密算法原理实现,课程设计报告置换加密解密文件读写_换位加密 解密 算法 python_Hares_的博客-程序员宅基地

python实验,置换加密解密算法原理实现,文件读取修改,课程实验置换密码加密解密过程,设明文为:4D 61 65 53 2D 4F 69 20 4E。密钥为8,1,6,3,5,7,4,9,2。求加密后的16进制密文。先思考和描述算法,也就是对明文4D 61 65 53 2D 4F 69 20 4E实现置换8,1,6,3,5,7,4,9,2。_换位加密 解密 算法 python

C_链表(精讲)_如何判断一个链表是否释放成功_Bright-SKY的博客-程序员宅基地

知识点1【链表的概述】(了解)1、数组特点:1、空间连续、元素类型相同、通过下标快速访问2、静态数组:空间一旦确定不能更改(动态数组除外)3、静态、动态数组 插入删除元素 需要移动大量数据2、链表的概述链表是一种物理存储上非连续,数据元素的逻辑连续通过链表节点中的指针变量保存下个节点的地址,实现的一种线性存储结构。3、链表的特点链表由一系列节点(链表中每一个元素称为节点)组成,节点在运行时动态生成(malloc,calloc),每个节点包 括两个部分:数据域:存放节点数据_如何判断一个链表是否释放成功

backtrader量化平台教程(一)框架简介_back trader_寻觅神迹的博客-程序员宅基地

为什么选择backtrader我们在投资的过程中,经常会有各种各样的idea。这些idea实际如何?如何评估。这时候我们需要使用历史数据对我们的idea进行回测。但是从零构筑一个回测框架,工作量和对技能的要求比较高。我们也没有必要为了吃个馒头而去种麦子。backtrader是这样一个基于python的回测框架。通过它我们可以快速的对策略进行回测验证我们的Idea。backtrader可以..._back trader

对于给定的权值进行Huffman编码_根据字符的权值进行哈夫曼编码_克怂是最帅的的博客-程序员宅基地

Huffman的特点是每次取出优先队列,也即是堆中最小的两个节点链接成一个新的节点,将新的节点放回到堆中。Huffman树每一个叶子都是一个字符。非叶子节点只是我们生成的节点,不是我们需要编码的字符。#include<iostream>#include<stdlib.h>#include<string.h>#include<queue>..._根据字符的权值进行哈夫曼编码

随便推点

SwiftUI ScrollView 自适应屏幕卡片组件 (教程含源码)_swiftui scrollview onappear_知识大胖的博客-程序员宅基地

实战需求SwiftUI ScrollView 自适应屏幕卡片组件本文价值与收获看完本文后,您将能够作出下面的界面看完本文您将掌握的技能掌握 ScrollView掌握 GeometryReader掌握 cornerRadius基础知识ScrollView一个可以滚动的视图struct ScrollView<Content> where Content : View滚动视图在可滚动内容区域内显示其内容。主题创建滚动视图1、init(Axis.Set, sh_swiftui scrollview onappear

JMeter 5.0 语音修改为简体中文(修改配置即可)_jmeter-captcha语音包_西边人细说测试的博客-程序员宅基地

打开apache-jmeter-5.0\bin\jmeter.properties 文件修改第三十七行,去掉前面的#,改为language=zh_CN重新打开就是中文界面了_jmeter-captcha语音包

openpyxl3.0官方文档(18)—— 坐标轴范围和对数缩放_openpyxl 图表 坐标轴设置_Sinchard的博客-程序员宅基地

坐标轴最小和最大值¶为了在图表上显示特定区域,可以手动设置坐标轴的最小值和最大值。 from openpyxl import Workbook from openpyxl.chart import ( ScatterChart, Reference, Series, ) wb = Workbook() ws = wb.active ws.append(['X', '1/X']) fo_openpyxl 图表 坐标轴设置

JAVA生成验证码,存放在redis做验证_java redis存入图片验证码时效性验证_IT界的老菜鸟的博客-程序员宅基地

import com.owinfo.utils.basetools.OwinfoStringUtil;import org.springframework.data.redis.core.RedisTemplate;import javax.imageio.ImageIO;import java.awt.*;import java.awt.image.BufferedImage;import java.awt.image.RenderedImage;import java.io.ByteAr._java redis存入图片验证码时效性验证

审计需要什么计算机技能,初入审计行业,应该掌握哪些技能?_JMLLJM的博客-程序员宅基地

原标题:初入审计行业,应该掌握哪些技能?现如今很多审计人员对未来感到很迷茫,这不单单是因为行业发展前景的问题,更多的是不知道怎么才能充实自己,更不知道如何才能让自己在行业中不断进步。其实单凭审计知识是远远不能在这个行业立足的,只有掌握多项技能才能有备无患。增强专业能力专业能力是审计行业发展的基础,目前来看最火热的莫过于注册会计师考试。其实说实话CPA这个东西不知道让多少人愁白了头,它是一个繁杂且漫...

es6关于函数和箭头函数指向的问题_天涯T_T浪人的博客-程序员宅基地

标题 箭头函数指向来看看this的一个使用案例:1.在函数中,settimeout没有被调用,指向window:2.箭头函数中,this指向定义时的this,而不是执行是的this:3.多层嵌套箭头函数:4.外层this指向window,内层this也会指向window:5.箭头函数,非箭头函数混合情况:...

推荐文章

热门文章

相关标签