The previous article recorded the RGB/YUV video pixel data processing method, this article continues the previous article the content, records the PCM audio sampling data processing method. The location of the audio sample data in the video player's decoding process is shown.
This paper introduces several PCM audio sampling data processing functions as follows:
Separating the left and right channels of the Pcm16le two-channel audio sampled data
Half the volume of the left channel in the Pcm16le two-channel audio sample data
Increases the sound speed of pcm16le two-channel audio sampled data by one-fold
Convert Pcm16le two-channel audio sample data to PCM8 audio sampled data
Capturing part of the data from Pcm16le Mono Audio sampling data
Convert Pcm16le two-channel audio sample data to wave format audio data
Note: PCM audio data can be viewed using audio editing software. For example, pay for professional audio editing software for Adobe Audition, or free open source audio editing software audacity.
List of functions
(1) Separating the left and right channels of the Pcm16le two-channel audio sampling data The functions in this program can separate the data from the left and right channels in the Pcm16le two-channel data into two files. The code for the function is shown below.
/** * Split left and right channel of 16LE PCM file. * @param URL location of the PCM file. * */int simplest_pcm16le_split (char *url) {file *fp=fopen (URL, "rb+"); FILE *fp1=fopen ("OUTPUT_L.PCM", "wb+"); FILE *fp2=fopen ("OUTPUT_R.PCM", "wb+"), unsigned char *sample= (unsigned char *) malloc (4); while (!feof (FP)) {fread ( SAMPLE,1,4,FP);//lfwrite (SAMPLE,1,2,FP1);//rfwrite (SAMPLE+2,1,2,FP2);} Free (sample); fclose (FP); fclose (FP1); fclose (FP2); return 0;}
The method that invokes the above function is shown below.
Simplest_pcm16le_split ("NOCTURNENO2INEFLAT_44.1K_S16LE.PCM");
As can be seen from the code, the sampled values of the left and right channels in the Pcm16le two-channel data are stored at intervals. Each sample value occupies 2Byte of space. After the code is run, the data in NOCTURNENO2INEFLAT_44.1K_S16LE.PCM's pcm16le format is separated into two mono data:
OUTPUT_L.PCM: Left channel data.
OUTPUT_R.PCM: Right channel data.
Note: The sampling frequency of the sound sample in this paper is all 44100Hz, and the sampling format is 16LE. "16" indicates that the number of sample bits is 16bit. Because of the 1byte=8bit, a sample value of one channel occupies 2Byte. "LE" stands for little Endian, which represents a 2 byte sample value stored in a high-level presence address.
Waveform for the input of the two-channel PCM data. The above waveform is the left-channel graph, and the waveform below is the right channel waveform. The horizontal axis is the time, the total length is 22 seconds, the ordinate is the sampling value, the value range from 32768 to 32767.
An audio waveform that output_l.pcm the left channel data after separation.
OUTPUT_R.PCM Audio waveform for the right channel data after separation.
(2) The volume of the left channel in the Pcm16le two-channel audio sample data is reduced by half the function in this program can reduce the volume of the left channel in the Pcm16le dual channel data by half. The code for the function is shown below.
/** * Halve volume of the left channel of 16LE PCM file * @param the URL location of the PCM file. */int Simplest_pcm16le_halfvolu Meleft (char *url) {FILE *fp=fopen (URL, "rb+"); FILE *fp1=fopen ("OUTPUT_HALFLEFT.PCM", "wb+"), int cnt=0;unsigned char *sample= (unsigned char *) malloc (4); while (!feof ( FP) {short *samplenum=null;fread (SAMPLE,1,4,FP), samplenum= (short *) Sample;*samplenum=*samplenum/2;//lfwrite ( SAMPLE,1,2,FP1);//rfwrite (SAMPLE+2,1,2,FP1); cnt++;} printf ("Sample cnt:%d\n", Cnt); free (sample); fclose (FP); fclose (FP1); return 0;}
The method that invokes the above function is shown below.
Simplest_pcm16le_halfvolumeleft ("NOCTURNENO2INEFLAT_44.1K_S16LE.PCM");
As can be seen from the source code, this program read out the left channel of 2 byte sampling value, as a C language of a short type of variable. After dividing the number by 2, it is written back to the PCM file. Waveform for input PCM two-channel audio sampled data.
The left channel of the output is treated with a waveform graph. You can see that the waveform amplitude of the left channel is reduced by half.
(3) Increase the sound speed of the Pcm16le two-channel audio sampling data by one time the functions in this program can increase the speed of Pcm16le two-channel data by an abstract way. The code for the function is shown below.
/** * Re-sample to double the speed of 16LE pcm file * @param URL at location of PCM file. */int simplest_pcm16le_doubles Peed (char *url) {FILE *fp=fopen (URL, "rb+"); FILE *fp1=fopen ("OUTPUT_DOUBLESPEED.PCM", "wb+"), int cnt=0;unsigned char *sample= (unsigned char *) malloc (4); while (! feof (FP)) {fread (SAMPLE,1,4,FP); if (cnt%2!=0) {//lfwrite (SAMPLE,1,2,FP1);//rfwrite (SAMPLE+2,1,2,FP1);} cnt++;} printf ("Sample cnt:%d\n", Cnt); free (sample); fclose (FP); fclose (FP1); return 0;}
The method that invokes the above function is shown below.
Simplest_pcm16le_doublespeed ("NOCTURNENO2INEFLAT_44.1K_S16LE.PCM");
As you can see from the source code, this procedure only samples the sample value of each sound Dodge number. After processing is completed, the original audio of about 22 seconds has changed to about 11 seconds. Audio plays up to twice times faster and the tone of the audio gets a lot higher. Waveform for input PCM two-channel audio sampled data.
A waveform for the output PCM dual-channel audio sample data. With the timeline you can see that the audio is much shorter.
(4) Convert pcm16le two-channel audio sample data to PCM8 audio sampled data
The functions in this program can be computed to convert the sample bits of the Pcm16le two-channel data 16bit to 8bit. The code for the function is shown below.
/** * Convert PCM-16 data to PCM-8 data. * @param URL location of the PCM file. */int simplest_pcm16le_to_pcm8 (char *url) {file *fp=fopen (URL, "rb+"); FILE *fp1=fopen ("OUTPUT_8.PCM", "wb+"), int cnt=0;unsigned char *sample= (unsigned char *) malloc (4); while (!feof (FP)) { Short *samplenum16=null;char samplenum8=0;unsigned Char samplenum8_u=0;fread (SAMPLE,1,4,FP);//(-32768-32767) samplenum16= (short *) sample;samplenum8= (*SAMPLENUM16) >>8;//(0-255) Samplenum8_u=samplenum8+128;//lfwrite ( &SAMPLENUM8_U,1,1,FP1); samplenum16= (short *) (sample+2); samplenum8= (*SAMPLENUM16) >>8;samplenum8_u= Samplenum8+128;//rfwrite (&SAMPLENUM8_U,1,1,FP1); cnt++;} printf ("Sample cnt:%d\n", Cnt); free (sample); fclose (FP); fclose (FP1); return 0;}
The method that invokes the above function is shown below.
SIMPLEST_PCM16LE_TO_PCM8 ("NOCTURNENO2INEFLAT_44.1K_S16LE.PCM");
The range of sampled data in the Pcm16le format is 32768 to 32767, whereas the range of sampled data in PCM8 format is 0 to 255. So Pcm16le conversion to PCM8 takes two steps: The first step is to convert the 16bit signed value from 32768 to 32767 to a 8bit signed value of 128 to 127, The second step is to convert the 8bit signed value from 128 to 127 to a 8bit unsigned value of 0 to 255. In this program, 16bit sampled data is stored through a short type variable, while 8bit sampled data is stored by unsigned char type. A waveform for the input 16bit PCM dual-channel audio sampled data.
A waveform for the output of 8bit PCM dual-channel audio sampled data. Note that the range of ordinate values in the observation diagram has changed to 0 to 255. If you listen carefully, you will find that the 8bit PCM's sound quality is significantly inferior to that of the PCM.
(5) Capture part of the data from the Pcm16le mono audio sample Data The functions in this program can intercept a piece of data from the Pcm16le mono data and output the sample value of the intercepted data. The code for the function is shown below.
/** * Cut a 16LE PCM single channel file. * @param URL location of the PCM file. * @param start_num start point * @param dur_num How much point to cut */int Simplest_pcm16le_cut_singlechannel (char *url,int start_num,int dur_num) {FILE *fp=fopen (URL, "rb+"); FILE *fp1=fopen ("OUTPUT_CUT.PCM", "wb+"); FILE *fp_stat=fopen ("Output_cut.txt", "wb+"), unsigned char *sample= (unsigned char *) malloc (2); int Cnt=0;while (!feof ( FP) {fread (SAMPLE,1,2,FP), if (cnt>start_num&&cnt<= (Start_num+dur_num)) {fwrite (SAMPLE,1,2,FP1); Short samplenum=sample[1];samplenum=samplenum*256;samplenum=samplenum+sample[0];fprintf (Fp_stat, "%6d,", Samplenum), if (cnt%10==0) fprintf (fp_stat, "\ n", samplenum);} cnt++;} Free (sample); fclose (FP); fclose (FP1); fclose (fp_stat); return 0;}
The method that invokes the above function is shown below.
Simplest_pcm16le_cut_singlechannel ("DRUM.PCM", 2360,120);
This program can select a sample value from the PCM data to be saved, and output the values of these samples. After the above code is run, the data of 120 points from 2,360 points in mono pcm16le format "DRUM.PCM" is saved to OUTPUT_CUT.PCM file. is the waveform of "DRUM.PCM", which has a sampling frequency of 44100KHz and a length of 0.5 seconds with a total of about 22,050 sample points.
The data in the OUTPUT_CUT.PCM file that was intercepted.
The sample values for the above data are listed below.
4460, 5192, 5956, 6680, 7199, 6706, 5727, 4481, 3261, 1993, 1264, 747, 767, 752, 1248, 1975, 2473, 2955, 2952, 2447, 974,- 1267,-4000, -6965,-10210,-13414,-16639,-19363,-21329,-22541,-23028,-22545,-21055,-19067,-16829,-14859,-12596,- 9900, -6684, -3475, -983, 1733, 3978, 5734, 6720, 6978, 6993, 7223, 7225, 7440, 7688, 8431, 8944, 9468, 9947, 10688, 11194, 11946, 12449, 12446, 12456, 11974, 11454, 10952, 10167, 9425, 8153, 6941, 5436, 3716, 1952, 236,- 1254, -2463, -3493, -4223, -4695, -4927, -5190, -4941, -4188, -2956, -1490, -40, 705, 932, 446, -776,-2512,-3994,-5723,-7201, -8687,-10157,-11134,-11661,-11642,-11168,-10155,-9142,-7888,-7146,-6186,- 5694, -4971, -4715, -4498, -4471, -4468, -4452, -4452, -3940, -2980, -1984, -752, 257, 1021, 1264,< c52/>1032, 31,
(6) Convert pcm16le two-channel audio sampled data to wave format audio Data Wave format audio (". wav") is the most common type of audio in Windows systems. The essence of this format is to add a file header in front of the PCM file. The function of this program can be encapsulated as wave format audio by adding a wave file header in front of the PCM file. The code for the function is shown below.
/** * Convert pcm16le raw data to WAVE format * @param pcmpath Input PCM file. * @param channels Channel number of PCM file. * @param sample_rate Sample rate of PCM file. * @param wavepath Output WAVE file. */int simplest_pcm16le_to_wave (const char *pcmpath,int channels,int sample_rate,const char *wavepath) {typedef struct wave_header{Char fccid[4]; unsigned long dwsize; Char fcctype[4]; }wave_header; typedef struct wave_fmt{char fccid[4]; unsigned long dwsize; unsigned short wformattag; unsigned short wchannels; unsigned long dwsamplespersec; unsigned long dwavgbytespersec; unsigned short wblockalign; unsigned short uibitspersample; }WAVE_FMT; typedef struct wave_data{char fccid[4]; unsigned long dwsize; }wave_data; if (channels==0| | sample_rate==0) {channels = 2; Sample_rate = 44100;} int bits = 16; Wave_heADER Pcmheader; WAVE_FMT pcmfmt; Wave_data Pcmdata; unsigned short m_pcmdata; FILE *fp,*fpout; Fp=fopen (Pcmpath, "RB"); if (fp = = NULL) {printf ("Open PCM file error\n"); return-1; }fpout=fopen (Wavepath, "wb+"); if (fpout = = NULL) {printf ("Create WAV file error\n"); return-1; }//wave_header memcpy (Pcmheader.fccid, "RIFF", strlen ("RIFF")); memcpy (Pcmheader.fcctype, "Wave", strlen ("wave")); Fseek (Fpout,sizeof (Wave_header), 1); WAVE_FMT pcmfmt.dwsamplespersec=sample_rate; Pcmfmt.dwavgbytespersec=pcmfmt.dwsamplespersec*sizeof (M_pcmdata); Pcmfmt.uibitspersample=bits; memcpy (Pcmfmt.fccid, "FMT", strlen ("FMT")); pcmfmt.dwsize=16; pcmfmt.wblockalign=2; Pcmfmt.wchannels=channels; pcmfmt.wformattag=1; Fwrite (&pcmfmt,sizeof (WAVE_FMT), 1,fpout); Wave_data; memcpy (pcmdata.fccid, "Data", strlen ("Data")); pcmdata.dwsize=0; Fseek (Fpout,sizeof (wave_data), seek_cur); Fread (&m_pcmdata,sizeof (unsigned short), 1,FP); while (!feof (FP)) {pcmdata.dwsize+=2; Fwrite (&m_pcmdata,sizeof (unsigned short), 1,fpout); Fread (&m_pcmdata,sizeof (unsigned short), 1,FP); } pcmheader.dwsize=44+pcmdata.dwsize; Rewind (fpout); Fwrite (&pcmheader,sizeof (Wave_header), 1,fpout); Fseek (Fpout,sizeof (WAVE_FMT), seek_cur); Fwrite (&pcmdata,sizeof (wave_data), 1,fpout); fclose (FP); Fclose (fpout); return 0;}
The method that invokes the above function is shown below.
Simplest_pcm16le_to_wave ("NOCTURNENO2INEFLAT_44.1K_S16LE.PCM", 2,44100, "output_nocturne.wav");
Wave file is a file in riff format. Its basic block name is "WAVE", which contains two sub-blocks "FMT" and "data". From the point of view of programming, it is composed of 4 parts: Wave_header, Wave_fmt, wave_data and sampling data. Its structure is shown below.
Wave_header |
Wave_fmt |
Wave_data |
PCM data |
The structure of the first 3 parts is shown below. When you write to the wave file header, assign the appropriate value to each of these fields. But one thing to note: Wave_header and Wave_data contain a dwsize field for file length information that must be obtained after the audio sampling data has been written. So the two structures are finally written to the wave file.
typedef struct WAVE_HEADER{CHAR fccid[4];unsigned long Dwsize;char fcctype[4];} wave_header;typedef struct Wave_fmt{char fccid[4];unsigned long dwsize;unsigned short wformattag;unsigned short wchannels;unsigned long dwsamplespersec;unsigned long dwavgbytespersec;unsigned short wblockalign;unsigned short Uibitspersample;} wave_fmt;typedef struct Wave_data{char fccid[4];unsigned long dwsize;} Wave_data;
After the function of this program is completed, the NOCTURNENO2INEFLAT_44.1K_S16LE.PCM file can be encapsulated into a output_nocturne.wav file.
Download
simplest mediadata test
Project Home
sourceforge:https://sourceforge.net/projects/simplest-mediadata-test/
Github:https://github.com/leixiaohua1020/simplest_mediadata_test
Open source China: http://git.oschina.net/leixiaohua1020/simplest_mediadata_test
csdn:http://download.csdn.net/detail/leixiaohua1020/9422409
This project contains several examples of audio and visual data parsing:
(1) Pixel data processing program. Functions that contain RGB and YUV pixel format processing.
(2) Audio sampling data processing program. A function that contains the processing of PCM audio sampling format.
(3) The Code Stream analysis program for H. Nalu can be detached and parsed.
(4) AAC Stream Analysis Program. Adts frames can be detached and parsed.
(5) FLV Encapsulation Format parser. You can separate the MP3 audio stream from the FLV.
(6) UDP-RTP Protocol Analysis Program. You can analyze the udp/rtp/mpeg-ts packets.
Rai (Lei Xiaohua)
[Email protected]
http://blog.csdn.net/leixiaohua1020
Getting Started with AV data processing: PCM Audio sampling data processing