speexdec.c
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:23k
源码类别:
Windows CE
开发平台:
C/C++
- /* Copyright (C) 2002-2003 Jean-Marc Valin
- File: speexdec.c
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- - Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- - Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- - Neither the name of the Xiph.org Foundation nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #ifdef HAVE_CONFIG_H
- # include "config.h"
- #endif
- #include <stdio.h>
- #if !defined WIN32 && !defined _WIN32
- #include <unistd.h>
- #include <getopt.h>
- #endif
- #ifndef HAVE_GETOPT_LONG
- #include "getopt_win.h"
- #endif
- #include <stdlib.h>
- #include <string.h>
- #include <speex/speex.h>
- #include <ogg/ogg.h>
- #if defined WIN32 || defined _WIN32
- #include <windows.h>
- #include "getopt_win.h"
- #include "wave_out.h"
- /* We need the following two to set stdout to binary */
- #include <io.h>
- #include <fcntl.h>
- #endif
- #include <math.h>
- #ifdef __MINGW32__
- #include "wave_out.c"
- #endif
- #ifdef HAVE_SYS_SOUNDCARD_H
- #include <sys/soundcard.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #elif defined HAVE_SYS_AUDIOIO_H
- #include <sys/types.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <sys/audioio.h>
- #ifndef AUDIO_ENCODING_SLINEAR
- #define AUDIO_ENCODING_SLINEAR AUDIO_ENCODING_LINEAR /* Solaris */
- #endif
- #endif
- #include <string.h>
- #include "wav_io.h"
- #include <speex/speex_header.h>
- #include <speex/speex_stereo.h>
- #include <speex/speex_callbacks.h>
- #include "wav_io.h"
- #define MAX_FRAME_SIZE 2000
- #define readint(buf, base) (((buf[base+3]<<24)&0xff000000)|
- ((buf[base+2]<<16)&0xff0000)|
- ((buf[base+1]<<8)&0xff00)|
- (buf[base]&0xff))
- static void print_comments(char *comments, int length)
- {
- char *c=comments;
- int len, i, nb_fields;
- char *end;
- if (length<8)
- {
- fprintf (stderr, "Invalid/corrupted commentsn");
- return;
- }
- end = c+length;
- len=readint(c, 0);
- c+=4;
- if (c+len>end)
- {
- fprintf (stderr, "Invalid/corrupted commentsn");
- return;
- }
- fwrite(c, 1, len, stderr);
- c+=len;
- fprintf (stderr, "n");
- if (c+4>end)
- {
- fprintf (stderr, "Invalid/corrupted commentsn");
- return;
- }
- nb_fields=readint(c, 0);
- c+=4;
- for (i=0;i<nb_fields;i++)
- {
- if (c+4>end)
- {
- fprintf (stderr, "Invalid/corrupted commentsn");
- return;
- }
- len=readint(c, 0);
- c+=4;
- if (c+len>end)
- {
- fprintf (stderr, "Invalid/corrupted commentsn");
- return;
- }
- fwrite(c, 1, len, stderr);
- c+=len;
- fprintf (stderr, "n");
- }
- }
- FILE *out_file_open(char *outFile, int rate, int *channels)
- {
- FILE *fout=NULL;
- /*Open output file*/
- if (strlen(outFile)==0)
- {
- #if defined HAVE_SYS_SOUNDCARD_H
- int audio_fd, format, stereo;
- audio_fd=open("/dev/dsp", O_WRONLY);
- if (audio_fd<0)
- {
- perror("Cannot open /dev/dsp");
- exit(1);
- }
- format=AFMT_S16_NE;
- if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format)==-1)
- {
- perror("SNDCTL_DSP_SETFMT");
- close(audio_fd);
- exit(1);
- }
- stereo=0;
- if (*channels==2)
- stereo=1;
- if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo)==-1)
- {
- perror("SNDCTL_DSP_STEREO");
- close(audio_fd);
- exit(1);
- }
- if (stereo!=0)
- {
- if (*channels==1)
- fprintf (stderr, "Cannot set mono mode, will decode in stereon");
- *channels=2;
- }
- if (ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate)==-1)
- {
- perror("SNDCTL_DSP_SPEED");
- close(audio_fd);
- exit(1);
- }
- fout = fdopen(audio_fd, "w");
- #elif defined HAVE_SYS_AUDIOIO_H
- audio_info_t info;
- int audio_fd;
- audio_fd = open("/dev/audio", O_WRONLY);
- if (audio_fd<0)
- {
- perror("Cannot open /dev/audio");
- exit(1);
- }
- AUDIO_INITINFO(&info);
- #ifdef AUMODE_PLAY /* NetBSD/OpenBSD */
- info.mode = AUMODE_PLAY;
- #endif
- info.play.encoding = AUDIO_ENCODING_SLINEAR;
- info.play.precision = 16;
- info.play.sample_rate = rate;
- info.play.channels = *channels;
- if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0)
- {
- perror ("AUDIO_SETINFO");
- exit(1);
- }
- fout = fdopen(audio_fd, "w");
- #elif defined WIN32 || defined _WIN32
- {
- unsigned int speex_channels = *channels;
- if (Set_WIN_Params (INVALID_FILEDESC, rate, SAMPLE_SIZE, speex_channels))
- {
- fprintf (stderr, "Can't access %sn", "WAVE OUT");
- exit(1);
- }
- }
- #else
- fprintf (stderr, "No soundcard supportn");
- exit(1);
- #endif
- } else {
- if (strcmp(outFile,"-")==0)
- {
- #if defined WIN32 || defined _WIN32
- _setmode(_fileno(stdout), _O_BINARY);
- #endif
- fout=stdout;
- }
- else
- {
- fout = fopen(outFile, "wb");
- if (!fout)
- {
- perror(outFile);
- exit(1);
- }
- if (strcmp(outFile+strlen(outFile)-4,".wav")==0 || strcmp(outFile+strlen(outFile)-4,".WAV")==0)
- write_wav_header(fout, rate, *channels, 0, 0);
- }
- }
- return fout;
- }
- void usage()
- {
- printf ("Usage: speexdec [options] input_file.spx [output_file]n");
- printf ("n");
- printf ("Decodes a Speex file and produce a WAV file or raw filen");
- printf ("n");
- printf ("input_file can be:n");
- printf (" filename.spx regular Speex filen");
- printf (" - stdinn");
- printf ("n");
- printf ("output_file can be:n");
- printf (" filename.wav Wav filen");
- printf (" filename.* Raw PCM file (any extension other that .wav)n");
- printf (" - stdoutn");
- printf (" (nothing) Will be played to soundcardn");
- printf ("n");
- printf ("Options:n");
- printf (" --enh Enable perceptual enhancement (default)n");
- printf (" --no-enh Disable perceptual enhancementn");
- printf (" --force-nb Force decoding in narrowbandn");
- printf (" --force-wb Force decoding in widebandn");
- printf (" --force-uwb Force decoding in ultra-widebandn");
- printf (" --mono Force decoding in monon");
- printf (" --stereo Force decoding in stereon");
- printf (" --rate n Force decoding at sampling rate n Hzn");
- printf (" --packet-loss n Simulate n %% random packet lossn");
- printf (" -V Verbose mode (show bit-rate)n");
- printf (" -h, --help This helpn");
- printf (" -v, --version Version informationn");
- printf (" --pf Deprecated, use --enh insteadn");
- printf (" --no-pf Deprecated, use --no-enh insteadn");
- printf ("n");
- printf ("More information is available from the Speex site: http://www.speex.orgn");
- printf ("n");
- printf ("Please report bugs to the mailing list `speex-dev@xiph.org'.n");
- }
- void version()
- {
- printf ("speexdec (Speex decoder) version " SPEEX_VERSION " (compiled " __DATE__ ")n");
- printf ("Copyright (C) 2002-2003 Jean-Marc Valinn");
- }
- void version_short()
- {
- printf ("speexdec version " SPEEX_VERSION "n");
- printf ("Copyright (C) 2002-2003 Jean-Marc Valinn");
- }
- static void *process_header(ogg_packet *op, int enh_enabled, int *frame_size, int *rate, int *nframes, int forceMode, int *channels, SpeexStereoState *stereo, int *extra_headers, int quiet)
- {
- void *st;
- const SpeexMode *mode;
- SpeexHeader *header;
- int modeID;
- SpeexCallback callback;
- header = speex_packet_to_header((char*)op->packet, op->bytes);
- if (!header)
- {
- fprintf (stderr, "Cannot read headern");
- return NULL;
- }
- if (header->mode >= SPEEX_NB_MODES)
- {
- fprintf (stderr, "Mode number %d does not (yet/any longer) exist in this versionn",
- header->mode);
- return NULL;
- }
- modeID = header->mode;
- if (forceMode!=-1)
- modeID = forceMode;
- mode = speex_lib_get_mode (modeID);
- if (header->speex_version_id > 1)
- {
- fprintf (stderr, "This file was encoded with Speex bit-stream version %d, which I don't know how to decoden", header->speex_version_id);
- return NULL;
- }
- if (mode->bitstream_version < header->mode_bitstream_version)
- {
- fprintf (stderr, "The file was encoded with a newer version of Speex. You need to upgrade in order to play it.n");
- return NULL;
- }
- if (mode->bitstream_version > header->mode_bitstream_version)
- {
- fprintf (stderr, "The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.n");
- return NULL;
- }
- st = speex_decoder_init(mode);
- if (!st)
- {
- fprintf (stderr, "Decoder initialization failed.n");
- return NULL;
- }
- speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled);
- speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size);
- if (!(*channels==1))
- {
- callback.callback_id = SPEEX_INBAND_STEREO;
- callback.func = speex_std_stereo_request_handler;
- callback.data = stereo;
- speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback);
- }
- if (!*rate)
- *rate = header->rate;
- /* Adjust rate if --force-* options are used */
- if (forceMode!=-1)
- {
- if (header->mode < forceMode)
- *rate <<= (forceMode - header->mode);
- if (header->mode > forceMode)
- *rate >>= (header->mode - forceMode);
- }
- speex_decoder_ctl(st, SPEEX_SET_SAMPLING_RATE, rate);
- *nframes = header->frames_per_packet;
- if (*channels==-1)
- *channels = header->nb_channels;
- if (!quiet)
- {
- fprintf (stderr, "Decoding %d Hz audio using %s mode",
- *rate, mode->modeName);
- if (*channels==1)
- fprintf (stderr, " (mono");
- else
- fprintf (stderr, " (stereo");
- if (header->vbr)
- fprintf (stderr, ", VBR)n");
- else
- fprintf(stderr, ")n");
- /*fprintf (stderr, "Decoding %d Hz audio at %d bps using %s moden",
- *rate, mode->bitrate, mode->modeName);*/
- }
- *extra_headers = header->extra_headers;
- free(header);
- return st;
- }
- int main(int argc, char **argv)
- {
- int c;
- int option_index = 0;
- char *inFile, *outFile;
- FILE *fin, *fout=NULL;
- short out[MAX_FRAME_SIZE];
- short output[MAX_FRAME_SIZE];
- int frame_size=0;
- void *st=NULL;
- SpeexBits bits;
- int packet_count=0;
- int stream_init = 0;
- int quiet = 0;
- ogg_int64_t page_granule=0, last_granule=0;
- int skip_samples=0, page_nb_packets;
- struct option long_options[] =
- {
- {"help", no_argument, NULL, 0},
- {"quiet", no_argument, NULL, 0},
- {"version", no_argument, NULL, 0},
- {"version-short", no_argument, NULL, 0},
- {"enh", no_argument, NULL, 0},
- {"no-enh", no_argument, NULL, 0},
- {"pf", no_argument, NULL, 0},
- {"no-pf", no_argument, NULL, 0},
- {"force-nb", no_argument, NULL, 0},
- {"force-wb", no_argument, NULL, 0},
- {"force-uwb", no_argument, NULL, 0},
- {"rate", required_argument, NULL, 0},
- {"mono", no_argument, NULL, 0},
- {"stereo", no_argument, NULL, 0},
- {"packet-loss", required_argument, NULL, 0},
- {0, 0, 0, 0}
- };
- ogg_sync_state oy;
- ogg_page og;
- ogg_packet op;
- ogg_stream_state os;
- int enh_enabled;
- int nframes=2;
- int print_bitrate=0;
- int close_in=0;
- int eos=0;
- int forceMode=-1;
- int audio_size=0;
- float loss_percent=-1;
- SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
- int channels=-1;
- int rate=0;
- int extra_headers;
- int wav_format=0;
- enh_enabled = 1;
- /*Process options*/
- while(1)
- {
- c = getopt_long (argc, argv, "hvV",
- long_options, &option_index);
- if (c==-1)
- break;
- switch(c)
- {
- case 0:
- if (strcmp(long_options[option_index].name,"help")==0)
- {
- usage();
- exit(0);
- } else if (strcmp(long_options[option_index].name,"quiet")==0)
- {
- quiet = 1;
- } else if (strcmp(long_options[option_index].name,"version")==0)
- {
- version();
- exit(0);
- } else if (strcmp(long_options[option_index].name,"version-short")==0)
- {
- version_short();
- exit(0);
- } else if (strcmp(long_options[option_index].name,"enh")==0)
- {
- enh_enabled=1;
- } else if (strcmp(long_options[option_index].name,"no-enh")==0)
- {
- enh_enabled=0;
- } else if (strcmp(long_options[option_index].name,"pf")==0)
- {
- fprintf (stderr, "--pf is deprecated, use --enh insteadn");
- enh_enabled=1;
- } else if (strcmp(long_options[option_index].name,"no-pf")==0)
- {
- fprintf (stderr, "--no-pf is deprecated, use --no-enh insteadn");
- enh_enabled=0;
- } else if (strcmp(long_options[option_index].name,"force-nb")==0)
- {
- forceMode=0;
- } else if (strcmp(long_options[option_index].name,"force-wb")==0)
- {
- forceMode=1;
- } else if (strcmp(long_options[option_index].name,"force-uwb")==0)
- {
- forceMode=2;
- } else if (strcmp(long_options[option_index].name,"mono")==0)
- {
- channels=1;
- } else if (strcmp(long_options[option_index].name,"stereo")==0)
- {
- channels=2;
- } else if (strcmp(long_options[option_index].name,"rate")==0)
- {
- rate=atoi (optarg);
- } else if (strcmp(long_options[option_index].name,"packet-loss")==0)
- {
- loss_percent = atof(optarg);
- }
- break;
- case 'h':
- usage();
- exit(0);
- break;
- case 'v':
- version();
- exit(0);
- break;
- case 'V':
- print_bitrate=1;
- break;
- case '?':
- usage();
- exit(1);
- break;
- }
- }
- if (argc-optind!=2 && argc-optind!=1)
- {
- usage();
- exit(1);
- }
- inFile=argv[optind];
- if (argc-optind==2)
- outFile=argv[optind+1];
- else
- outFile = "";
- wav_format = strlen(outFile)>=4 && (
- strcmp(outFile+strlen(outFile)-4,".wav")==0
- || strcmp(outFile+strlen(outFile)-4,".WAV")==0);
- /*Open input file*/
- if (strcmp(inFile, "-")==0)
- {
- #if defined WIN32 || defined _WIN32
- _setmode(_fileno(stdin), _O_BINARY);
- #endif
- fin=stdin;
- }
- else
- {
- fin = fopen(inFile, "rb");
- if (!fin)
- {
- perror(inFile);
- exit(1);
- }
- close_in=1;
- }
- /*Init Ogg data struct*/
- ogg_sync_init(&oy);
- speex_bits_init(&bits);
- /*Main decoding loop*/
- while (1)
- {
- char *data;
- int i, j, nb_read;
- /*Get the ogg buffer for writing*/
- data = ogg_sync_buffer(&oy, 200);
- /*Read bitstream from input file*/
- nb_read = fread(data, sizeof(char), 200, fin);
- ogg_sync_wrote(&oy, nb_read);
- /*Loop for all complete pages we got (most likely only one)*/
- while (ogg_sync_pageout(&oy, &og)==1)
- {
- int packet_no;
- if (stream_init == 0) {
- ogg_stream_init(&os, ogg_page_serialno(&og));
- stream_init = 1;
- }
- /*Add page to the bitstream*/
- ogg_stream_pagein(&os, &og);
- page_granule = ogg_page_granulepos(&og);
- page_nb_packets = ogg_page_packets(&og);
- if (page_granule>0 && frame_size)
- {
- skip_samples = page_nb_packets*frame_size*nframes - (page_granule-last_granule);
- if (ogg_page_eos(&og))
- skip_samples = -skip_samples;
- /*else if (!ogg_page_bos(&og))
- skip_samples = 0;*/
- } else
- {
- skip_samples = 0;
- }
- /*printf ("page granulepos: %d %d %dn", skip_samples, page_nb_packets, (int)page_granule);*/
- last_granule = page_granule;
- /*Extract all available packets*/
- packet_no=0;
- while (!eos && ogg_stream_packetout(&os, &op)==1)
- {
- /*If first packet, process as Speex header*/
- if (packet_count==0)
- {
- st = process_header(&op, enh_enabled, &frame_size, &rate, &nframes, forceMode, &channels, &stereo, &extra_headers, quiet);
- if (!nframes)
- nframes=1;
- if (!st)
- exit(1);
- fout = out_file_open(outFile, rate, &channels);
- } else if (packet_count==1)
- {
- if (!quiet)
- print_comments((char*)op.packet, op.bytes);
- } else if (packet_count<=1+extra_headers)
- {
- /* Ignore extra headers */
- } else {
- int lost=0;
- packet_no++;
- if (loss_percent>0 && 100*((float)rand())/RAND_MAX<loss_percent)
- lost=1;
- /*End of stream condition*/
- if (op.e_o_s)
- eos=1;
- /*Copy Ogg packet to Speex bitstream*/
- speex_bits_read_from(&bits, (char*)op.packet, op.bytes);
- for (j=0;j!=nframes;j++)
- {
- int ret;
- /*Decode frame*/
- if (!lost)
- ret = speex_decode_int(st, &bits, output);
- else
- ret = speex_decode_int(st, NULL, output);
- /*for (i=0;i<frame_size*channels;i++)
- printf ("%dn", (int)output[i]);*/
- if (ret==-1)
- break;
- if (ret==-2)
- {
- fprintf (stderr, "Decoding error: corrupted stream?n");
- break;
- }
- if (speex_bits_remaining(&bits)<0)
- {
- fprintf (stderr, "Decoding overflow: corrupted stream?n");
- break;
- }
- if (channels==2)
- speex_decode_stereo_int(output, frame_size, &stereo);
- if (print_bitrate) {
- int tmp;
- char ch=13;
- speex_decoder_ctl(st, SPEEX_GET_BITRATE, &tmp);
- fputc (ch, stderr);
- fprintf (stderr, "Bitrate is use: %d bps ", tmp);
- }
- /*Convert to short and save to output file*/
- if (strlen(outFile)!=0)
- {
- for (i=0;i<frame_size*channels;i++)
- out[i]=le_short(output[i]);
- } else {
- for (i=0;i<frame_size*channels;i++)
- out[i]=output[i];
- }
- {
- int frame_offset = 0;
- int new_frame_size = frame_size;
- /*printf ("packet %d %dn", packet_no, skip_samples);*/
- if (packet_no == 1 && j==0 && skip_samples > 0)
- {
- /*printf ("chopping first packetn");*/
- new_frame_size -= skip_samples;
- frame_offset = skip_samples;
- }
- if (packet_no == page_nb_packets && skip_samples < 0)
- {
- int packet_length = nframes*frame_size+skip_samples;
- new_frame_size = packet_length - j*frame_size;
- if (new_frame_size<0)
- new_frame_size = 0;
- if (new_frame_size>frame_size)
- new_frame_size = frame_size;
- /*printf ("chopping end: %d %d %dn", new_frame_size, packet_length, packet_no);*/
- }
- if (new_frame_size)
- {
- #if defined WIN32 || defined _WIN32
- if (strlen(outFile)==0)
- WIN_Play_Samples (out+frame_offset*channels, sizeof(short) * new_frame_size*channels);
- else
- #endif
- fwrite(out+frame_offset*channels, sizeof(short), new_frame_size*channels, fout);
- audio_size+=sizeof(short)*new_frame_size*channels;
- }
- }
- }
- }
- packet_count++;
- }
- }
- if (feof(fin))
- break;
- }
- if (wav_format)
- {
- if (fseek(fout,4,SEEK_SET)==0)
- {
- int tmp;
- tmp = le_int(audio_size+36);
- fwrite(&tmp,4,1,fout);
- if (fseek(fout,32,SEEK_CUR)==0)
- {
- tmp = le_int(audio_size);
- fwrite(&tmp,4,1,fout);
- } else
- {
- fprintf (stderr, "First seek worked, second didn'tn");
- }
- } else {
- fprintf (stderr, "Cannot seek on wave file, size will be incorrectn");
- }
- }
- if (st)
- speex_decoder_destroy(st);
- else
- {
- fprintf (stderr, "This doesn't look like a Speex filen");
- }
- speex_bits_destroy(&bits);
- if (stream_init)
- ogg_stream_clear(&os);
- ogg_sync_clear(&oy);
- #if defined WIN32 || defined _WIN32
- if (strlen(outFile)==0)
- WIN_Audio_close ();
- #endif
- if (close_in)
- fclose(fin);
- if (fout != NULL)
- fclose(fout);
- return 0;
- }