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

📄 aq.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 2 页
字号:
static void alloc_soft_queue(void){    int i;    char *base;    if(base_buckets)    {	free(base_buckets[0].data);	free(base_buckets);	base_buckets = NULL;    }    base_buckets = (AudioBucket *)safe_malloc(nbuckets * sizeof(AudioBucket));    base = (char *)safe_malloc(nbuckets * bucket_size);    for(i = 0; i < nbuckets; i++)	base_buckets[i].data = base + i * bucket_size;    flush_buckets();}/* aq_fill_one() transfers one audio bucket to device. */static int aq_fill_one(void){    AudioBucket *tmp;    if(head == NULL)	return 0;    if(aq_output_data(head->data, bucket_size) == -1)	return -1;    tmp = head;    head = head->next;    reuse_audio_bucket(tmp);    return 0;}/* aq_fill_nonblocking() transfers some audio buckets to device. * This function is non-blocking.  But it is possible to block because * of miss-estimated aq_fillable() calculation. */int aq_fill_nonblocking(void){    int32 i, nfills;    AudioBucket *tmp;    if(head == NULL || head->len != bucket_size || !IS_STREAM_TRACE)	return 0;    nfills = (aq_fillable() * Bps) / bucket_size;    for(i = 0; i < nfills; i++)    {	if(head == NULL || head->len != bucket_size)	    break;	if(aq_output_data(head->data, bucket_size) == -1)	    return RC_ERROR;	tmp = head;	head = head->next;	reuse_audio_bucket(tmp);    }    return 0;}int32 aq_samples(void){    double realtime, es;    int s;    if(play_mode->acntl(PM_REQ_GETSAMPLES, &s) != -1)    {	/* Reset counter & timer */	if(play_counter)	{	    play_start_time = get_current_calender_time();	    play_offset_counter = s;	    play_counter = 0;	}	return s;    }    if(!IS_STREAM_TRACE)	return -1;    realtime = get_current_calender_time();    if(play_counter == 0)    {	play_start_time = realtime;	return play_offset_counter;    }    es = play_mode->rate * (realtime - play_start_time);    if(es >= play_counter)    {	/* Ouch!	 * Audio device queue may be empty!	 * Reset counters.	 */	play_offset_counter += play_counter;	play_counter = 0;	play_start_time = realtime;	return play_offset_counter;    }    return (int32)es + play_offset_counter;}int32 aq_filled(void){    double realtime, es;    int filled;    if(!IS_STREAM_TRACE)	return 0;    if(play_mode->acntl(PM_REQ_GETFILLED, &filled) != -1)      return filled;    realtime = get_current_calender_time();    if(play_counter == 0)    {	play_start_time = realtime;	return 0;    }    es = play_mode->rate * (realtime - play_start_time);    if(es >= play_counter)    {	/* out of play counter */	play_offset_counter += play_counter;	play_counter = 0;	play_start_time = realtime;	return 0;    }    return play_counter - (int32)es;}int32 aq_soft_filled(void){    int32 bytes;    AudioBucket *cur;    bytes = 0;    for(cur = head; cur != NULL; cur = cur->next)	bytes += cur->len;    return bytes / Bps;}int32 aq_fillable(void){    int fillable;    if(!IS_STREAM_TRACE)	return 0;    if(play_mode->acntl(PM_REQ_GETFILLABLE, &fillable) != -1)	return fillable;    return device_qsize / Bps - aq_filled();}double aq_filled_ratio(void){    double ratio;    if(!IS_STREAM_TRACE)	return 1.0;    ratio = (double)aq_filled() * Bps / device_qsize;    if(ratio > 1.0)	return 1.0; /* for safety */    return ratio;}int aq_get_dev_queuesize(void){    if(!IS_STREAM_TRACE)	return 0;    return device_qsize / Bps;}int aq_soft_flush(void){    int rc;    while(head)    {	if(head->len < bucket_size)	{	    /* Add silence code */	    memset (head->data + head->len, 0, bucket_size - head->len);	    head->len = bucket_size;	}	if(aq_fill_one() == -1)	    return RC_ERROR;	trace_loop();	rc = check_apply_control();	if(RC_IS_SKIP_FILE(rc))	{	    play_mode->acntl(PM_REQ_DISCARD, NULL);	    flush_buckets();	    return rc;	}    }    play_mode->acntl(PM_REQ_OUTPUT_FINISH, NULL);    return RC_NONE;}int aq_flush(int discard){    int rc;    int more_trace;    /* to avoid infinite loop */    double t, timeout_expect;    aq_add_count = 0;    init_effect();    if(discard)    {	trace_flush();	if(play_mode->acntl(PM_REQ_DISCARD, NULL) != -1)	{	    flush_buckets();	    return RC_NONE;	}	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,		  "ERROR: Can't discard audio buffer");    }    if(!IS_STREAM_TRACE)    {	play_mode->acntl(PM_REQ_FLUSH, NULL);	play_counter = play_offset_counter = 0;	return RC_NONE;    }    rc = aq_soft_flush();    if(RC_IS_SKIP_FILE(rc))	return rc;    more_trace = 1;    t = get_current_calender_time();    timeout_expect = t + (double)aq_filled() / play_mode->rate;    while(more_trace || aq_filled() > 0)    {	rc = check_apply_control();	if(RC_IS_SKIP_FILE(rc))	{	    play_mode->acntl(PM_REQ_DISCARD, NULL);	    flush_buckets();	    return rc;	}	more_trace = trace_loop();	t = get_current_calender_time();	if(t >= timeout_expect - 0.1)	  break;	if(!more_trace)	  usleep((unsigned long)((timeout_expect - t) * 1000000));	else	  aq_wait_ticks();    }    trace_flush();    play_mode->acntl(PM_REQ_FLUSH, NULL);    flush_buckets();    return RC_NONE;}/* Wait a moment */static void aq_wait_ticks(void){    int32 trace_wait, wait_samples;    if(device_qsize == 0 ||       (trace_wait = trace_wait_samples()) == 0)	return; /* No wait */    wait_samples = (device_qsize / Bps) / 5; /* 20% */    if(trace_wait != -1 && /* There are more trace events */       trace_wait < wait_samples)	wait_samples = trace_wait;    usleep((unsigned int)((double)wait_samples / play_mode->rate * 1000000.0));}/* add_play_bucket() attempts to add buf to audio bucket. * It returns actually added bytes. */static int add_play_bucket(const char *buf, int n){    int total;    if(n == 0)	return 0;    if(!nbuckets) {      play_mode->output_data((char *)buf, n);      return n;    }    if(head == NULL)	head = tail = next_allocated_bucket();    total = 0;    while(n > 0)    {	int i;	if(tail->len == bucket_size)	{	    AudioBucket *b;	    if((b = next_allocated_bucket()) == NULL)		break;	    if(head == NULL)		head = tail = b;	    else		tail = tail->next = b;	}	i = bucket_size - tail->len;	if(i > n)	    i = n;	memcpy(tail->data + tail->len, buf + total, i);	total += i;	n     -= i;	tail->len += i;    }    return total;}/* Flush and clear audio bucket */static void flush_buckets(void){    int i;    allocated_bucket_list = NULL;    for(i = 0; i < nbuckets; i++)	reuse_audio_bucket(&base_buckets[i]);    head = tail = NULL;    aq_fill_buffer_flag = (aq_start_count > 0);    play_counter = play_offset_counter = 0;}/* next_allocated_bucket() gets free bucket.  If all buckets is used, it * returns NULL. */static AudioBucket *next_allocated_bucket(void){    AudioBucket *b;    if(allocated_bucket_list == NULL)	return NULL;    b = allocated_bucket_list;    allocated_bucket_list = allocated_bucket_list->next;    b->len = 0;    b->next = NULL;    return b;}/* Reuse specified bucket */static void reuse_audio_bucket(AudioBucket *bucket){    bucket->next = allocated_bucket_list;    allocated_bucket_list = bucket;}

⌨️ 快捷键说明

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