⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aq.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    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    aq.c - Audio queue.	      Written by Masanao Izumo <mo@goice.co.jp>*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#include <stdlib.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include "timidity.h"#include "common.h"#include "output.h"#include "aq.h"#include "timer.h"#include "controls.h"#include "miditrace.h"#include "instrum.h"#include "playmidi.h"#define TEST_SPARE_RATE 0.9#define MAX_BUCKET_TIME 0.2#define MAX_FILLED_TIME 2.0static int32 device_qsize;static int Bps;	/* Bytes per sample frame */static int bucket_size;static int nbuckets = 0;static double bucket_time;int aq_fill_buffer_flag = 0;static int32 aq_start_count;static int32 aq_add_count;static int32 play_counter, play_offset_counter;static double play_start_time;typedef struct _AudioBucket{    char *data;    int len;    struct _AudioBucket *next;} AudioBucket;static AudioBucket *base_buckets = NULL;static AudioBucket *allocated_bucket_list = NULL;static AudioBucket *head = NULL;static AudioBucket *tail = NULL;static void alloc_soft_queue(void);static int add_play_bucket(const char *buf, int n);static void reuse_audio_bucket(AudioBucket *bucket);static AudioBucket *next_allocated_bucket(void);static void flush_buckets(void);static int aq_fill_one(void);static void aq_wait_ticks(void);static int32 estimate_queue_size(void);/* effect.c */extern void init_effect(void);extern int do_effect(int32* buf, int32 count);int aq_calc_fragsize(void){    int ch, bps, bs;    double dq, bt;    if(play_mode->encoding & PE_MONO)	ch = 1;    else	ch = 2;    if(play_mode->encoding & PE_24BIT)	bps = ch * 3;    else if(play_mode->encoding & PE_16BIT)	bps = ch * 2;    else	bps = ch;    bs = audio_buffer_size * bps;    dq = play_mode->rate * MAX_FILLED_TIME * bps;    while(bs * 2 > dq)	bs /= 2;    bt = (double)bs / bps / play_mode->rate;    while(bt > MAX_BUCKET_TIME)    {	bs /= 2;	bt = (double)bs / bps / play_mode->rate;    }    return bs;}void aq_setup(void){    int ch;    /* Initialize Bps, bucket_size, device_qsize, and bucket_time */    if(play_mode->encoding & PE_MONO)	ch = 1;    else	ch = 2;    if(play_mode->encoding & PE_24BIT)	Bps = 3 * ch;    else if(play_mode->encoding & PE_16BIT)	Bps = 2 * ch;    else	Bps = ch;    if(play_mode->acntl(PM_REQ_GETFRAGSIZ, &bucket_size) == -1)	bucket_size = audio_buffer_size * Bps;    bucket_time = (double)bucket_size / Bps / play_mode->rate;    if(IS_STREAM_TRACE)    {	if(play_mode->acntl(PM_REQ_GETQSIZ, &device_qsize) == -1)	    device_qsize = estimate_queue_size();	if(bucket_size * 2 > device_qsize) {	  ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,		    "Warning: Audio buffer is too small.");	  device_qsize = 0;	} else {	  device_qsize -= device_qsize % Bps; /* Round Bps */	  ctl->cmsg(CMSG_INFO, VERB_DEBUG,		    "Audio device queue size: %d bytes", device_qsize);	  ctl->cmsg(CMSG_INFO, VERB_DEBUG,		    "Write bucket size: %d bytes (%d msec)",		    bucket_size, (int)(bucket_time * 1000 + 0.5));	}    }    else    {	device_qsize = 0;	if(base_buckets)	{	    free(base_buckets[0].data);	    free(base_buckets);	    base_buckets = NULL;	}	nbuckets = 0;    }    init_effect();    aq_add_count = 0;}void aq_set_soft_queue(double soft_buff_time, double fill_start_time){    static double last_soft_buff_time, last_fill_start_time;    int nb;    /* for re-initialize */    if(soft_buff_time < 0)	soft_buff_time = last_soft_buff_time;    if(fill_start_time < 0)	fill_start_time = last_fill_start_time;    nb = (int)(soft_buff_time / bucket_time);    if(nb == 0)	aq_start_count = 0;    else	aq_start_count = (int32)(fill_start_time * play_mode->rate);    aq_fill_buffer_flag = (aq_start_count > 0);    if(nbuckets != nb)    {	nbuckets = nb;	alloc_soft_queue();    }    last_soft_buff_time = soft_buff_time;    last_fill_start_time = fill_start_time;}/* Estimates the size of audio device queue. * About sun audio, there are long-waiting if buffer of device audio is full. * So it is impossible to completely estimate the size. */static int32 estimate_queue_size(void){    char *nullsound;    double tb, init_time, chunktime;    int32 qbytes, max_qbytes;    int ntries;    nullsound = (char *)safe_malloc(bucket_size);    memset(nullsound, 0, bucket_size);    if(play_mode->encoding & (PE_ULAW|PE_ALAW))	general_output_convert((int32 *)nullsound, bucket_size/Bps);    tb = play_mode->rate * Bps * TEST_SPARE_RATE;    ntries = 1;    max_qbytes = play_mode->rate * MAX_FILLED_TIME * Bps;  retry:    chunktime = (double)bucket_size / Bps / play_mode->rate;    qbytes = 0;    init_time = get_current_calender_time();	/* Start */    for(;;)    {	double start, diff;	start = get_current_calender_time();	if(start - init_time > 1.0) /* ?? */	{	    ctl->cmsg(CMSG_WARNING, VERB_DEBUG,		      "Warning: Audio test is terminated");	    break;	}	play_mode->output_data(nullsound, bucket_size);	diff = get_current_calender_time() - start;	if(diff > chunktime/2 || qbytes > 1024*512 || chunktime < diff)	    break;	qbytes += (int32)((chunktime - diff) * tb);	if(qbytes > max_qbytes)	{	    qbytes = max_qbytes;	    break;	}    }    play_mode->acntl(PM_REQ_DISCARD, NULL);    if(bucket_size * 2 > qbytes)    {	if(ntries == 4)	{	    ctl->cmsg(CMSG_ERROR, VERB_NOISY,		      "Can't estimate audio queue length");	    bucket_size = audio_buffer_size * Bps;	    free(nullsound);	    return 2 * audio_buffer_size * Bps;	}	ctl->cmsg(CMSG_WARNING, VERB_DEBUG,		  "Retry to estimate audio queue length (%d times)",		  ntries);	bucket_size /= 2;	ntries++;	goto retry;    }    free(nullsound);    return qbytes;}/* Send audio data to play_mode->output_data() */static int aq_output_data(char *buff, int nbytes){    int i;    play_counter += nbytes / Bps;    while(nbytes > 0)    {	i = nbytes;	if(i > bucket_size)	    i = bucket_size;	if(play_mode->output_data(buff, i) == -1)	    return -1;	nbytes -= i;	buff += i;    }    return 0;}int aq_add(int32 *samples, int32 count){    int32 nbytes, i;    char *buff;    if(!(play_mode->flag & PF_PCM_STREAM))	return 0;    if(!count)    {	if(!aq_fill_buffer_flag)	    return aq_fill_nonblocking();	return 0;    }    aq_add_count += count;    do_effect(samples, count);    nbytes = general_output_convert(samples, count);    buff = (char *)samples;    if(device_qsize == 0)      return play_mode->output_data(buff, nbytes);    aq_fill_buffer_flag = (aq_add_count <= aq_start_count);    if(!aq_fill_buffer_flag)	if(aq_fill_nonblocking() == -1)	    return -1;    if(!ctl->trace_playing)    {	while((i = add_play_bucket(buff, nbytes)) < nbytes)	{	    buff += i;	    nbytes -= i;	    if(head && head->len == bucket_size)	    {		if(aq_fill_one() == -1)		    return -1;	    }	    aq_fill_buffer_flag = 0;	}	return 0;    }    trace_loop();    while((i = add_play_bucket(buff, nbytes)) < nbytes)    {	/* Software buffer is full.	 * Write one bucket to audio device.	 */	buff += i;	nbytes -= i;	aq_wait_ticks();	trace_loop();	if(aq_fill_nonblocking() == -1)	    return -1;	aq_fill_buffer_flag = 0;    }    return 0;}/* alloc_soft_queue() (re-)initializes audio buckets. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -