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

📄 darwin_a.c

📁 MIDI解码程序(用VC编写)
💻 C
字号:
/* -*- c-file-style: "gnu" -*-    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>    ALSA 0.[56] support by Katsuhiro Ueno <katsu@blue.sky.or.jp>    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., 675 Mass Ave, Cambridge, MA 02139, USA.    darwin_a.c    Functions to play sound on the Darwin audio driver    by T.Nogami <t-nogami@happy.email.ne.jp>*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include <CoreAudio/AudioHardware.h>#include "timidity.h"#include "common.h"#include "output.h"#include "controls.h"#include "timer.h"#include "instrum.h"#include "playmidi.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 in_bytes);static int acntl(int request, void *arg);static int total_bytes;float output_volume = 1.0;int	    mac_buf_using_num;/* export the playback mode *//*********************************************************************/#define dpm darwin_play_modePlayMode dpm = {  DEFAULT_RATE, PE_16BIT|PE_SIGNED, PF_PCM_STREAM|PF_CAN_TRACE,  -1,  {0}, /* default: get all the buffer fragments you can */  "Mac OS X pcm device", 'd',  "",  open_output,  close_output,  output_data,  acntl};#define FailWithAction(cond, action, handler)				\	if (cond) {							\		{ action; }						\		goto handler;						\	}//#define DEBUG_DARWIN_A(x)   /*nothing*/#define DEBUG_DARWIN_A(x)   ctl->cmsg x;/*********************************************************************/typedef struct {    Boolean		soundPlaying;    AudioDeviceID	device;			// the default device    UInt32	        deviceBufferSize;                  // bufferSize returned by kAudioDevicePropertyBufferSize    AudioStreamBasicDescription		deviceFormat;                  // info about the default device#define BUFNUM 256#define BUFLEN 4096    char             buffer[BUFNUM][BUFLEN];   //1 buffer size = 4096bytes    unsigned short   buffer_len[BUFNUM];    volatile int     currBuf, nextBuf;    int		     samples, get_samples;} appGlobals, *appGlobalsPtr, **appGlobalsHandle;	static appGlobals	globals;/*********************************************************************/OSStatus appIOProc (AudioDeviceID  inDevice, const AudioTimeStamp*  inNow,                    const AudioBufferList*  inInputData,		    const AudioTimeStamp*  inInputTime,                     AudioBufferList*  outOutputData,		    const AudioTimeStamp* inOutputTime, void* dummy ){    int       next_curr;    int       trans_len;            if( globals.currBuf==globals.nextBuf ){  //end of play        outOutputData->mNumberBuffers=0;        memset(outOutputData->mBuffers[0].mData, 0, globals.deviceBufferSize);        globals.soundPlaying=0;        return 0;    }        trans_len = globals.buffer_len[globals.currBuf];    if( output_volume==1.0 ){        memcpy(  outOutputData->mBuffers[0].mData,             &globals.buffer[globals.currBuf][0],              trans_len);   // move data into output data buffer    }else{        float   *src = (float*)&globals.buffer[globals.currBuf][0],                *dst = outOutputData->mBuffers[0].mData;        int     i, quant = trans_len/sizeof(float);        for(i=0; i<quant; i++){            *dst++ = (*src++)*output_volume;        }    }    outOutputData->mBuffers[0].mDataByteSize = trans_len;        outOutputData->mNumberBuffers=1;    globals.samples += trans_len                              / globals.deviceFormat.mBytesPerPacket;        next_curr = globals.currBuf+1;    next_curr %= BUFNUM;    mac_buf_using_num--;    globals.currBuf = next_curr;        return 0; //no err}/*********************************************************************/static void init_variable(){    globals.samples = globals.get_samples = 0;    globals.currBuf = globals.nextBuf = 0;    globals.soundPlaying = 0;    mac_buf_using_num = 0;}/*********************************************************************//*return value == 0 sucess *             == -1 fails */static int open_output(void){    OSStatus				err = 0; //no err    UInt32				count,                                        bufferSize;    AudioDeviceID			device = kAudioDeviceUnknown;    AudioStreamBasicDescription		format;    // get the default output device for the HAL    count = sizeof(globals.device);    // it is required to pass the size of the data to be returned    err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,                                   &count, (void *) &device);    if (err != 0) goto Bail;        // get the buffersize that the default device uses for IO    count = sizeof(globals.deviceBufferSize);              // it is required to pass the size of the data to be returned    err = AudioDeviceGetProperty(device, 0, 0, kAudioDevicePropertyBufferSize,                                 &count, &bufferSize);    if (err != 0) goto Bail;       if( globals.deviceBufferSize>BUFLEN ){        fprintf(stderr, "globals.deviceBufferSize NG: %ld\n",                globals.deviceBufferSize);        exit(1);    }            // get a description of the data format used by the default device    count = sizeof(globals.deviceFormat);         // it is required to pass the size of the data to be returned    err = AudioDeviceGetProperty(device, 0, 0,                                 kAudioDevicePropertyStreamFormat,                                 &count, &format);    if (err != 0) goto Bail;    FailWithAction(format.mFormatID != kAudioFormatLinearPCM, err = -1, Bail);                    // bail if the format is not linear pcm        // everything is ok so fill in these globals    globals.device = device;    globals.deviceBufferSize = bufferSize;    globals.deviceFormat = format;    init_variable();        err = AudioDeviceAddIOProc(globals.device, appIOProc, 0 );                    // setup our device with an IO proc    if (err != 0) goto Bail;    globals.deviceFormat.mSampleRate = dpm.rate;#if 0    globals.deviceFormat.mFormatFlags =  kLinearPCMFormatFlagIsBigEndian                                       | kLinearPCMFormatFlagIsPacked                                       | kLinearPCMFormatFlagIsSignedInteger;    globals.deviceFormat.mBytesPerPacket = 4;    globals.deviceFormat.mBytesPerFrame = 4;    globals.deviceFormat.mBitsPerChannel = 0x10;        err = AudioDeviceSetProperty(device, &inWhen, 0, 0,                                 kAudioDevicePropertyStreamFormat,                                 count, &globals.deviceFormat);    if (err != 0) goto Bail;#endif#if 0    fprintf(stderr, "deviceBufferSize = %d\n", globals.deviceBufferSize);    fprintf(stderr, "mSampleRate = %g\n", globals.deviceFormat.mSampleRate);    fprintf(stderr, "mFormatID = 0x%08x\n", globals.deviceFormat.mFormatID);    fprintf(stderr, "mFormatFlags = 0x%08x\n",            globals.deviceFormat.mFormatFlags);    fprintf(stderr, "mBytesPerPacket = 0x%08x\n",            globals.deviceFormat.mBytesPerPacket);    fprintf(stderr, "mBytesPerFrame = 0x%08x\n",            globals.deviceFormat.mBytesPerFrame);    fprintf(stderr, "mBitsPerChannel = 0x%08x\n",            globals.deviceFormat.mBitsPerChannel);#endifBail:    return (err);}/*********************************************************************/static int output_data(char *buf, int32 in_bytes){    OSStatus		err = 0;    int         next_nextbuf, out_bytes;    int         inBytesPerQuant, max_quant, max_outbytes, out_quant, i;    float       maxLevel;        //quant  : 1 value    //packet : 1 pair of quant(stereo data)    if (dpm.encoding & PE_16BIT){            inBytesPerQuant = 2;            maxLevel=32768.0;    }else if(dpm.encoding & PE_24BIT){            inBytesPerQuant = 3;            maxLevel=8388608.0;    }else{            ctl->cmsg(CMSG_ERROR, VERB_NORMAL,                "Sorry, not support 8bit sound.");            exit(1);    }        max_outbytes = globals.deviceBufferSize;    max_quant    = max_outbytes / sizeof(float);         redo:    out_quant = in_bytes/inBytesPerQuant;    out_bytes= out_quant * sizeof(float);    if( out_bytes > max_outbytes ){        out_bytes = max_outbytes;    }    out_quant = out_bytes/sizeof(float);    out_quant &=0xfffffffe;  //trunc to eaven number for stereo    out_bytes = out_quant*sizeof(float);        next_nextbuf = globals.nextBuf+1;    next_nextbuf %= BUFNUM;        while( globals.currBuf==next_nextbuf ){ //queue full        usleep(100000); //0.1sec    }        switch( inBytesPerQuant ){      case 2:        for( i=0; i<out_quant; i++){            ((float*)(globals.buffer[globals.nextBuf]))[i] =                              ((short*)buf)[i]/maxLevel;        }	   break;      case 3:	    for( i=0; i<out_quant; i++ ){	              ((float*)(globals.buffer[globals.nextBuf]))[i] =                             (*(int32*)&buf[i*3]>>8) / maxLevel;	    }	    break;    }                globals.buffer_len[globals.nextBuf] = out_bytes;        if( globals.soundPlaying == 0){      err = AudioDeviceStart(globals.device, appIOProc);      if (err != 0) goto Bail;                        // start playing sound through the device      globals.soundPlaying = 1;   // set the playing status global to true             }    globals.nextBuf = next_nextbuf;        in_bytes -= out_quant*inBytesPerQuant;    buf += out_quant*inBytesPerQuant;    mac_buf_using_num++;    globals.get_samples += out_bytes/globals.deviceFormat.mBytesPerPacket;        if( in_bytes ){        goto redo;    }     Bail:    return (err);} /*********************************************************************/static void close_output(void){    OSStatus 	err = 0;        err = AudioDeviceStop(globals.device, appIOProc);                            // stop playing sound through the device    if (err != 0) goto Bail;    err = AudioDeviceRemoveIOProc(globals.device, appIOProc);                       // remove the IO proc from the device    if (err != 0) goto Bail;        globals.soundPlaying = 0;                    // set the playing status global to falseBail:;}/*********************************************************************/static int acntl(int request, void *arg){    switch (request){      case PM_REQ_GETFRAGSIZ:	if( dpm.encoding & PE_24BIT ){	  *((int *)arg) = 3072;	  	}else{	  *((int *)arg) = BUFLEN;	}	return 0;            case PM_REQ_GETSAMPLES:          *((int *)arg) = globals.samples;          return 0;    case PM_REQ_DISCARD:          AudioDeviceStop(globals.device, appIOProc);	  init_variable();          return 0;	      case PM_REQ_PLAY_START:	init_variable();	return 0;	    case PM_REQ_FLUSH:    case PM_REQ_OUTPUT_FINISH:        while( globals.soundPlaying ){	    trace_loop();	    usleep(1000);	}	init_variable();	return 0;        default:        break;    }    return -1;}

⌨️ 快捷键说明

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