📄 speex_a.c
字号:
/* TiMidity++ -- MIDI to WAVE converter and player Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp> Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA speex_a.c Written by Iwata <b6330015@kit.jp> Functions to output Ogg Speex (*.ogg).*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#if HAVE_UNISTD_H#include <unistd.h>#endif#ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#include <speex.h>#include <speex_header.h>#include <ogg/ogg.h>#include "timidity.h"#include "output.h"#include "controls.h"#include "timer.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "miditrace.h"static int open_output(void); /* 0=success, 1=warning, -1=fatal error */static void close_output(void);static int output_data(char *buf, int32 nbytes);static int acntl(int request, void *arg);/* export the playback mode */#define dpm speex_play_modePlayMode dpm = { DEFAULT_RATE, PE_SIGNED|PE_16BIT, PF_PCM_STREAM, -1, {0}, "Ogg Speex", 'S', NULL, open_output, close_output, output_data, acntl};#define MAX_FRAME_SIZE 2000#define MAX_FRAME_BYTES 2000typedef struct { /* Ogg */ ogg_stream_state os; ogg_page og; ogg_packet op; int ogg_packetid; /* Speex */ SpeexHeader header; SpeexBits bits; SpeexMode* mode; void* state; int frame_size; int nframes; int channels; /* state */ unsigned long in_bytes; unsigned long out_bytes; /* simple buffer */ float *input; int input_idx;} Speex_ctx;static int ogg_seqnum = 0;static Speex_ctx *speex_ctx = NULL;typedef struct { int quality; int vbr; int abr; int vad; int dtx; int complexity; int nframes;} Speex_options;Speex_options speex_options = { 8, /* quality */ 0, /* vbr */ 0, /* abr */ 0, /* vad */ 0, /* dtx */ 3, /* complexity */ 1 /* nframes */};/* code from speexenc.c */static int speex_mode_preset(){ int rate = dpm.rate; Speex_ctx *ctx = speex_ctx; if (speex_ctx == NULL) return 0; if (ctx->mode == NULL) { if (rate > 48000) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "sampling rate too high: %d Hz,\n" "try down-sampling\n", rate); return 0; } else if (rate > 25000) { ctx->mode = &speex_uwb_mode; } else if (rate > 12500) { ctx->mode = &speex_wb_mode; } else if (rate >= 6000) { ctx->mode = &speex_nb_mode; } else { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Sampling rate too low: %d Hz\n", rate); return 0; } } if (rate != 8000 && rate != 16000 && rate != 32000) ctl->cmsg(CMSG_WARNING, VERB_NORMAL, "Speex is only optimized for 8, 16 and 32 kHz.\n" "It will still work at %d Hz but your mileage may vary", rate); return 1;}void speex_set_option_quality(int quality){ speex_options.quality = quality; if (quality < 0) speex_options.quality = 0; if (10 < quality) speex_options.quality = 10;}void speex_set_option_vbr(int vbr){ speex_options.vbr = vbr;}void speex_set_option_abr(int rate){ speex_options.abr = rate;}void speex_set_option_vad(int vad){ speex_options.vad = vad;}void speex_set_option_dtx(int dtx){ speex_options.dtx = dtx;}void speex_set_option_complexity(int complexity){ speex_options.complexity = complexity; if (complexity < 0) speex_options.complexity = 0; if (10 < complexity) speex_options.complexity = 10;}void speex_set_option_nframes(int nframes){ speex_options.nframes = nframes; if (nframes < 1) speex_options.nframes = 0; if (10 < nframes) speex_options.nframes = 10;}/* Write an Ogg page to a file pointer code from speexenc.c*/int oe_write_page(ogg_page *page, int fd){ int written = 0; written += write(fd, page->header, page->header_len); written += write(fd, page->body, page->body_len); return written;}#define writeint(buf, base, val) do { buf[base+3]=((val)>>24)&0xff; \ buf[base+2]=((val)>>16)&0xff; \ buf[base+1]=((val)>>8)&0xff; \ buf[base]=(val)&0xff; \ } while(0)void comment_init(char **comments, int* length, char *vendor_string){ int vendor_length = strlen(vendor_string); int user_comment_list_length = 0; int len= 4 + vendor_length + 4; char *p = (char*)safe_malloc(len); writeint(p, 0, vendor_length); memcpy(p + 4, vendor_string, vendor_length); writeint(p, 4 + vendor_length, user_comment_list_length); *length = len; *comments = p;}/* Write header (format will change) code from speexenc.c*/int write_ogg_header(Speex_ctx *ctx, int fd, char *comments){ int ret, result; char *vendor_string = "Encoded with Timidity++-" VERSION "(compiled " __DATE__ ")"; int comments_length = strlen(comments); comment_init(&comments, &comments_length, vendor_string); ctx->op.packet = (unsigned char *)speex_header_to_packet(&ctx->header, (int*)&(ctx->op.bytes)); ctx->op.b_o_s = 1; ctx->op.e_o_s = 0; ctx->op.granulepos = 0; ctx->op.packetno = 0; ogg_stream_packetin(&ctx->os, &ctx->op); free(ctx->op.packet); ctx->op.packet = (unsigned char *)comments; ctx->op.bytes = comments_length; ctx->op.b_o_s = 0; ctx->op.e_o_s = 0; ctx->op.granulepos = 0; ctx->op.packetno = 1; ogg_stream_packetin(&ctx->os, &ctx->op); while((result = ogg_stream_flush(&ctx->os, &ctx->og))) { if(!result) break; ret = oe_write_page(&ctx->og, fd); if(ret != ctx->og.header_len + ctx->og.body_len) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "failed writing header to output Ogg stream\n"); return 1; } else ctx->out_bytes += ret; } return 0;}static int speex_output_open(const char *fname, const char *comment){ Speex_ctx *ctx; int fd; if (!(speex_ctx = (Speex_ctx *)calloc(sizeof(Speex_ctx), 1))) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s", strerror(errno)); return -1; } ctx = speex_ctx; /* init id */ ctx->in_bytes = ctx->out_bytes = 0; ctx->ogg_packetid = -1; ctx->channels = (dpm.encoding & PE_MONO) ? 1 : 2; if(strcmp(fname, "-") == 0) { fd = 1; /* data to stdout */ if(comment == NULL) comment = "(stdout)"; } else { /* Open the audio file */ fd = open(fname, FILE_OUTPUT_MODE); if (fd < 0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", fname, strerror(errno)); return -1; } } /*Initialize Ogg stream struct*/ if (ogg_seqnum == 0) { srand(time(NULL)); ogg_seqnum = rand(); } if (ogg_stream_init(&ctx->os, ogg_seqnum++) == -1) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Ogg stream init failed\n"); return -1; } if (!speex_mode_preset()) return -1; speex_init_header(&ctx->header, dpm.rate, 1, ctx->mode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -