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

📄 nas_a.c

📁 MIDI解码程序(用VC编写)
💻 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>    nas_a.c - Copyright (C) 1999 Michael Haardt <michael@moria.de>    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    nas_a.c    Functions to play sound on the Network Audio System*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <audio/audiolib.h>#include <audio/soundlib.h>#include <stdio.h>#include <stdlib.h>#ifndef NO_STRING_H /* for memmove */#include <string.h>#else#include <strings.h>#endif#include "timidity.h"#include "common.h"#include "output.h"#include "controls.h"#include "timer.h"#include "instrum.h"#include "playmidi.h"#include "miditrace.h"#define BUFFERED_SECS 3#define LOW_WATER_PERCENT 40#ifdef LITTLE_ENDIAN#define LINEAR16_FORMAT AuFormatLinearSigned16LSB#else#define LINEAR16_FORMAT AuFormatLinearSigned16MSB#endif#define dpm nas_play_modestatic int opendevaudio(void);static void closedevaudio(void);static int writedevaudio(char *buf, int32 len);static int ioctldevaudio(int request, void *arg);PlayMode dpm={  DEFAULT_RATE,  PE_16BIT|PE_SIGNED,  PF_PCM_STREAM|PF_CAN_TRACE,  -1,  {0},  "Network Audio Server", 'n',  (char*)0,  opendevaudio,  closedevaudio,  writedevaudio,  ioctldevaudio};struct DevAudio{  AuServer *aud;  AuFlowID flow;  char *data;  AuUint32 used;  AuUint32 capacity;  AuBool synced;  AuBool finished;};static struct DevAudio fd;static int32 output_counter, play_counter, reset_samples;static double play_start_time;static void reset_sample_counters(){    output_counter = play_counter = reset_samples = 0;}static int32 current_samples(void){    double realtime, es;    realtime = get_current_calender_time();    if(play_counter == 0)    {	play_start_time = realtime;	return reset_samples;    }    es = dpm.rate * (realtime - play_start_time);    if(es >= play_counter)    {	/* out of play counter */	reset_samples += play_counter;	play_counter = 0;	play_start_time = realtime;	return reset_samples;    }    if(es < 0)	return 0; /* for safety */    return (int32)es + reset_samples;}static void play(struct DevAudio *fd, AuUint32 len){  int count;  count = len;  if(!(dpm.encoding & PE_MONO))      count /= 2;  if(dpm.encoding & PE_16BIT)      count /= 2;  if (len<fd->used)   {    AuWriteElement(fd->aud,fd->flow,0,len,fd->data,AuFalse,(AuStatus*)0);    memmove(fd->data,fd->data+len,fd->used-=len);  }  else   {    AuWriteElement(fd->aud,fd->flow,0,fd->used,fd->data,len!=fd->used,(AuStatus*)0);    fd->used=0;  }  fd->synced=AuTrue;  current_samples();	/* Update sample counter */  play_counter += count;}static AuBool nas_eventHandler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *handler){  struct DevAudio *fd=(struct DevAudio*)handler->data;  switch (ev->type)  {    case AuEventTypeMonitorNotify:    {      fd->finished=AuTrue;      break;    }    case AuEventTypeElementNotify:    {      AuElementNotifyEvent *event=(AuElementNotifyEvent*)ev;      switch (event->kind)      {        case AuElementNotifyKindLowWater:        {          play(fd,event->num_bytes);          break;        }        case AuElementNotifyKindState: switch (event->cur_state)        {          case AuStatePause:          {            if (event->reason!=AuReasonUser) play(fd,event->num_bytes);            break;          }          case AuStateStop:          {            fd->finished=AuTrue;            break;          }        }      }    }  }  return AuTrue;}static void syncdevaudio(void){  AuEvent ev;  while ((!fd.synced) && (!fd.finished))   {    AuNextEvent(fd.aud,AuTrue,&ev);    AuDispatchEvent(fd.aud,&ev);  }  fd.synced=AuFalse;}static int opendevaudio(void){  AuDeviceID device=AuNone;  AuElement elements[2];  AuUint32 buf_samples;  int i;  /* Only supported PE_16BIT|PE_SIGNED yet */  dpm.encoding = validate_encoding(dpm.encoding,				   PE_16BIT|PE_SIGNED,				   PE_BYTESWAP|PE_ULAW|PE_ALAW);   if (!(fd.aud = AuOpenServer((char*)0, 0, NULL, 0, NULL, NULL))) return -1;  fd.capacity = 0;  for (i=0; i<AuServerNumDevices(fd.aud); ++i)  {    if    (      AuDeviceKind(AuServerDevice(fd.aud,i))==AuComponentKindPhysicalOutput      && AuDeviceNumTracks(AuServerDevice(fd.aud,i))==((dpm.encoding&PE_MONO)?1:2)    )    {      device=AuDeviceIdentifier(AuServerDevice(fd.aud,i));      break;    }  }  if (device==AuNone) return -1;  if (!(fd.flow=AuCreateFlow(fd.aud,NULL))) return -1;  buf_samples = dpm.rate*BUFFERED_SECS;  AuMakeElementImportClient(&elements[0],dpm.rate,LINEAR16_FORMAT,(dpm.encoding&PE_MONO)?1:2,AuTrue,buf_samples,(AuUint32) (buf_samples/100*LOW_WATER_PERCENT),0,NULL);  AuMakeElementExportDevice(&elements[1],0,device,dpm.rate,AuUnlimitedSamples,0,NULL);  AuSetElements(fd.aud,fd.flow,AuTrue,2,elements,NULL);  AuRegisterEventHandler(fd.aud,AuEventHandlerIDMask,0,fd.flow,nas_eventHandler,(AuPointer)&fd);  fd.capacity = buf_samples*((dpm.encoding&PE_MONO)?1:2)*AuSizeofFormat(LINEAR16_FORMAT);  if ((fd.data=malloc(fd.capacity))==(char*)0) return -1;  fd.used = 0;  fd.synced = AuFalse;  fd.finished = AuFalse;  AuStartFlow(fd.aud,fd.flow,NULL);  dpm.fd = 0;  reset_sample_counters();  return 0;}static void closedevaudio(void){  if(dpm.fd != -1)  {    AuStopFlow(fd.aud, fd.flow, NULL);    while (!fd.finished) syncdevaudio();    AuCloseServer(fd.aud);    free(fd.data);    dpm.fd = 0;  }}static int writedevaudio(char *buf, int32 len){  int done = 0;  while ((fd.used+(len-done))>fd.capacity)  {    int stillFits=fd.capacity-fd.used;    memcpy(fd.data+fd.used,buf+done,stillFits);    done+=stillFits;    fd.used+=stillFits;    syncdevaudio();  }  memcpy(fd.data+fd.used,buf+done,len-done);  fd.used+=(len-done);  output_counter += len;  return len;}static int ioctldevaudio(int request, void *arg){  switch (request)  {    case PM_REQ_DISCARD:      if(!output_counter)	  return 0;      AuStopFlow(fd.aud,fd.flow,NULL);      /* Restart playing is not work correctly.       * I don't know what I should do, so I re-open audio server.       */#if 0      AuStartFlow(fd.aud,fd.flow,NULL);      reset_sample_counters();      return 0;#else      AuCloseServer(fd.aud);      free(fd.data);      return opendevaudio();#endif    case PM_REQ_FLUSH:      reset_sample_counters();      return 0;    case PM_REQ_GETSAMPLES:      if(play_counter)	  *(int *)arg = current_samples();      else	  *(int *)arg = reset_samples;      return 0;    case PM_REQ_PLAY_START:      reset_sample_counters();      return 0;  }  return -1;}

⌨️ 快捷键说明

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