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

📄 audio.c

📁 音频信号的重采样程序,如44.1K的WAV转换成采样频率为48K的WAV.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Audio hardware handlers (SGI, OSS, ALSA, Sun, Windows, Mac OSX, Jack, ESD, HPUX, NetBSD) *//* * layout of this file: *    error handlers *    SGI new and old audio library *    OSS (with Sam 9407 support) *    ALSA *    Sun (has switches for OpenBSD, but they're untested) *    Windows 95/98 *    OSX *    ESD *    JACK *    HPUX *    NetBSD *    audio describers *//* * void mus_audio_describe(void) describes the audio hardware state. * char *mus_audio_report(void) returns the same information as a string. * * int mus_audio_open_output(int dev, int srate, int chans, int format, int size) * int mus_audio_open_input(int dev, int srate, int chans, int format, int size) * int mus_audio_write(int line, char *buf, int bytes) * int mus_audio_close(int line) * int mus_audio_read(int line, char *buf, int bytes) * * int mus_audio_mixer_read(int dev, int field, int chan, float *val) * int mus_audio_mixer_write(int dev, int field, int chan, float *val) * int mus_audio_initialize(void) does whatever is needed to get set up * int mus_audio_systems(void) returns number of separate complete audio systems (soundcards essentially) * AUDIO_SYSTEM(n) selects the nth card (counting from 0), AUDIO_SYSTEM(0) is always the default * char *mus_audio_system_name(int system) returns some user-recognizable (?) name for the given card (don't free) * char *mus_audio_moniker(void) returns some brief description of the overall audio setup (don't free return string). *//* error handling is tricky here -- higher levels are using many calls as probes, so *   the "error" is a sign of non-existence, not a true error.  So, for nearly all *   cases, I'll use mus_print, not mus_error. */#include <mus-config.h>#if USE_SND && MUS_MAC_OSX && USE_MOTIF  #undef USE_MOTIF  #define USE_NO_GUI 1  /* Xt's Boolean (/usr/include/X11/Intrinsic.h = char) collides with MacTypes.h Boolean, (actually,   *   unsigned char in /Developer/SDKs/MacOSX10.4u.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CFBase.h)   *   but we want snd.h for other stuff, so, if Motif is in use, don't load its headers at this time   *   perhaps we could use the -funsigned-char switch in gcc   */#endif#if USE_SND && MUS_MAC_OSX && HAVE_RUBY  /* if using Ruby, OpenTransport.h T_* definitions collide with Ruby's -- it isn't needed here, so... */  #define REDEFINE_HAVE_RUBY 1  #undef HAVE_RUBY#endif#if USE_SND  #include "snd.h"#else  #define PRINT_BUFFER_SIZE 512  #define LABEL_BUFFER_SIZE 64#endif#if USE_SND && MUS_MAC_OSX  #define USE_MOTIF 1  #undef USE_NO_GUI  #if REDEFINE_HAVE_RUBY    #define HAVE_RUBY 1  #endif#endif#include <math.h>#include <stdio.h>#if HAVE_FCNTL_H  #include <fcntl.h>#endif#include <errno.h>#include <stdlib.h>#if (defined(HAVE_LIBC_H) && (!defined(HAVE_UNISTD_H)))  #include <libc.h>#else  #if (!(defined(_MSC_VER)))    #include <unistd.h>  #endif#endif#if HAVE_STRING_H  #include <string.h>#endif#if HAVE_SAM_9407  #include <sys/sam9407.h>#endif#ifdef MUS_MAC_OSX#include <CoreServices/CoreServices.h>#include <CoreAudio/CoreAudio.h>/* these pull in stdbool.h apparently, so they have to precede sndlib.h */#endif#include "_sndlib.h"#include "sndlib-strings.h"#if (!HAVE_STRERROR)char *strerror(int errnum){  char *strerrbuf;  strerrbuf = (char *)CALLOC(LABEL_BUFFER_SIZE, sizeof(char));  mus_snprintf(strerrbuf, LABEL_BUFFER_SIZE, "io err %d", errnum);  return(strerrbuf);}#endif#define MUS_STANDARD_ERROR(Error_Type, Error_Message) \  mus_print("%s\n  [%s[%d] %s]", Error_Message, __FILE__, __LINE__, c__FUNCTION__)#define MUS_STANDARD_IO_ERROR(Error_Type, IO_Func, IO_Name) \  mus_print("%s %s: %s\n  [%s[%d] %s]", IO_Func, IO_Name, strerror(errno), __FILE__, __LINE__, c__FUNCTION__)static char *version_name = NULL;static bool audio_initialized = false;static const char *mus_audio_device_names[] = {  S_mus_audio_default, S_mus_audio_duplex_default, S_mus_audio_adat_in, S_mus_audio_aes_in, S_mus_audio_line_out,  S_mus_audio_line_in, S_mus_audio_microphone, S_mus_audio_speakers, S_mus_audio_digital_in, S_mus_audio_digital_out,  S_mus_audio_dac_out, S_mus_audio_adat_out, S_mus_audio_aes_out, S_mus_audio_dac_filter, S_mus_audio_mixer,  S_mus_audio_line1, S_mus_audio_line2, S_mus_audio_line3, S_mus_audio_aux_input, S_mus_audio_cd,  S_mus_audio_aux_output, S_mus_audio_spdif_in, S_mus_audio_spdif_out, S_mus_audio_amp, S_mus_audio_srate,  S_mus_audio_channel, S_mus_audio_format, S_mus_audio_imix, S_mus_audio_igain, S_mus_audio_reclev,  S_mus_audio_pcm, S_mus_audio_pcm2, S_mus_audio_ogain, S_mus_audio_line, S_mus_audio_synth,  S_mus_audio_bass, S_mus_audio_treble, S_mus_audio_port, S_mus_audio_samples_per_channel,  S_mus_audio_direction};static const char *mus_audio_device_name(int dev){  if (MUS_AUDIO_DEVICE_OK(dev))    return(mus_audio_device_names[dev]);  return("invalid device");}#if (!HAVE_OSS) || (HAVE_ALSA)static const char *mus_audio_format_names[] = {  "unknown", S_mus_bshort, S_mus_mulaw, S_mus_byte, S_mus_bfloat, S_mus_bint, S_mus_alaw, S_mus_ubyte, S_mus_b24int,  S_mus_bdouble, S_mus_lshort, S_mus_lint, S_mus_lfloat, S_mus_ldouble, S_mus_ubshort, S_mus_ulshort, S_mus_l24int,  S_mus_bintn, S_mus_lintn};static const char *mus_audio_format_name(int fr){  if (MUS_DATA_FORMAT_OK(fr))    return(mus_audio_format_names[fr]);  return("invalid format");}#endifstatic char *audio_strbuf = NULL; /* previous name "strbuf" collides with Mac OSX global! */static void pprint(char *str);int device_channels(int dev);int device_gains(int dev);int device_channels(int dev){  float val[4];#if USE_SND && MUS_DEBUGGING  XEN res;  res = XEN_EVAL_C_STRING("(if (defined? 'debugging-device-channels) debugging-device-channels 0)");  if (XEN_INTEGER_P(res))    {      int chans;      chans = XEN_TO_C_INT(res);      if (chans > 0) return(chans);    }#endif  mus_audio_mixer_read(dev, MUS_AUDIO_CHANNEL, 0, val);  return((int)val[0]);}int device_gains(int ur_dev){  float val[4];  int err;  int dev;  dev = MUS_AUDIO_DEVICE(ur_dev);  /* to get hardware gains, read device amp_field and error = none */  if ((dev == MUS_AUDIO_DAC_FILTER) || (dev == MUS_AUDIO_MIXER))     {      err = mus_audio_mixer_read(ur_dev, MUS_AUDIO_CHANNEL, 0, val);#ifdef HAVE_ALSA      if (err != MUS_NO_ERROR) return(0);#endif      return((int)val[0]);    }  err = mus_audio_mixer_read(ur_dev, MUS_AUDIO_AMP, 0, val);  if (err != MUS_NO_ERROR) return(0);  return(device_channels(ur_dev));}/* ------------------------------- SGI ----------------------------------------- */#ifdef MUS_SGI#define AUDIO_OK#include <audio.h>int mus_audio_systems(void) {return(1);} /* I think more than 1 is possible, but don't have a case to test with */char *mus_audio_system_name(int system) {return("SGI");}char *mus_audio_moniker(void) {#ifdef AL_RESOURCE  return("New SGI audio");#else  return("Old SGI audio");#endif}#ifndef AL_RESOURCEstatic char *alGetErrorString(int err){  switch (err)    {    case AL_BAD_NOT_IMPLEMENTED:   return("not implemented yet");                   break;    case AL_BAD_PORT:              return("tried to use an invalid port");          break;    case AL_BAD_CONFIG:            return("tried to use an invalid configuration"); break;    case AL_BAD_DEVICE:            return("tried to use an invalid device");        break;    case AL_BAD_DEVICE_ACCESS:     return("unable to access the device");           break;    case AL_BAD_DIRECTION:         return("invalid direction given for port");      break;    case AL_BAD_OUT_OF_MEM:        return("operation has run out of memory");       break;    case AL_BAD_NO_PORTS:          return("not able to allocate a port");           break;    case AL_BAD_WIDTH:             return("invalid sample width given");            break;    case AL_BAD_ILLEGAL_STATE:     return("an invalid state has occurred");         break;    case AL_BAD_QSIZE:             return("attempt to set an invalid queue size");  break;    case AL_BAD_FILLPOINT:         return("attempt to set an invalid fillpoint");   break;    case AL_BAD_BUFFER_NULL:       return("null buffer pointer");                   break;    case AL_BAD_COUNT_NEG:         return("negative count");                        break;    case AL_BAD_PVBUFFER:          return("param/val buffer doesn't make sense");   break;    case AL_BAD_BUFFERLENGTH_NEG:  return("negative buffer length");                break;    case AL_BAD_BUFFERLENGTH_ODD:  return("odd length parameter/value buffer");     break;    case AL_BAD_CHANNELS:          return("invalid channel specifier");             break;    case AL_BAD_PARAM:             return("invalid parameter");                     break;    case AL_BAD_SAMPFMT:           return("attempt to set invalid sample format");  break;    case AL_BAD_RATE:              return("invalid sample rate token");             break;    case AL_BAD_TRANSFER_SIZE:     return("invalid size for sample read/write");    break;    case AL_BAD_FLOATMAX:          return("invalid size for floatmax");             break;    case AL_BAD_PORTSTYLE:         return("invalid port style");                    break;    default:                       return("");    }}#endifstatic char *sgi_err_buf = NULL;static mus_print_handler_t *old_handler = NULL;static void sgi_mus_print(char *msg){  int oserr = oserror();  if (oserr)    {      if (sgi_err_buf == NULL) sgi_err_buf = (char *)CALLOC(PRINT_BUFFER_SIZE, sizeof(char));      mus_snprintf(sgi_err_buf, PRINT_BUFFER_SIZE, "%s [%s]", msg, alGetErrorString(oserr));      (*old_handler)(sgi_err_buf);    }  else (*old_handler)(msg);}static void start_sgi_print(void){  if (old_handler != sgi_mus_print)    old_handler = mus_print_set_handler(sgi_mus_print);}static void end_sgi_print(void){  if (old_handler != sgi_mus_print)    mus_print_set_handler(old_handler);  else mus_print_set_handler(NULL);}#if AL_RESOURCE  #define al_free(Line)                  alFreeConfig(config[Line])  #define al_newconfig()                 alNewConfig()  #define al_setsampfmt(Line, Format)    alSetSampFmt(Line, Format)  #define al_setchannels(Line, Chans)    alSetChannels(Line, Chans)  #define al_setwidth(Line, Width)       alSetWidth(Line, Width)  #define al_setqueuesize(Line, Size)    alSetQueueSize(Line, Size)  #define al_openport(Name, Flag, Line)  alOpenPort(Name, Flag, Line)  #define al_getfilled(Port)             alGetFilled(Port)  #define al_closeport(Port)             alClosePort(Port)  #define al_freeconfig(Config)          alFreeConfig(Config)#else  #define al_free(Line)                  ALfreeconfig(config[Line]);  #define al_newconfig()                 ALnewconfig()  #define al_setsampfmt(Line, Format)    ALsetsampfmt(Line, Format)  #define al_setchannels(Line, Chans)    ALsetchannels(Line, Chans)  #define al_setwidth(Line, Width)       ALsetwidth(Line, Width)  #define al_setqueuesize(Line, Size)    ALsetqueuesize(Line, Size)  #define al_openport(Name, Flag, Line)  ALopenport(Name, Flag, Line)  #define al_getfilled(Port)             ALgetfilled(Port)  #define al_closeport(Port)             ALcloseport(Port)  #define al_freeconfig(Config)          ALfreeconfig(Config)#endif#define RETURN_ERROR_EXIT(Error_Type, Audio_Line, Ur_Error_Message) \  do { \      char *Error_Message; Error_Message = Ur_Error_Message; \      if (Audio_Line != -1) al_free(Audio_Line); \      if (Error_Message) \        { \          MUS_STANDARD_ERROR(Error_Type, Error_Message); FREE(Error_Message); \        } \      else MUS_STANDARD_ERROR(Error_Type, mus_error_type_to_string(Error_Type)); \      end_sgi_print(); \      return(MUS_ERROR); \      } while (false)#ifdef AL_RESOURCEstatic int check_queue_size(int size, int chans) {  if (size > chans * 1024)    return(size);  else return(chans * 1024);}#else#define STEREO_QUEUE_MIN_SIZE 1024#define STEREO_QUEUE_MIN_CHOICE 1024/* docs say 510 or 512, but they die with "File size limit exceeded" %$@#!(& */#define MONO_QUEUE_MIN_SIZE 1019#define MONO_QUEUE_MIN_CHOICE 1024#define STEREO_QUEUE_MAX_SIZE 131069#define STEREO_QUEUE_MAX_CHOICE 65536#define MONO_QUEUE_MAX_SIZE 262139#define MONO_QUEUE_MAX_CHOICE 131072/* if these limits are not followed, the damned thing dumps core and dies */static int check_queue_size(int size, int chans){  if ((chans == 1) && (size > MONO_QUEUE_MAX_SIZE)) return(MONO_QUEUE_MAX_CHOICE);  if ((chans == 1) && (size < MONO_QUEUE_MIN_SIZE)) return(MONO_QUEUE_MIN_CHOICE);  if ((chans > 1) && (size > STEREO_QUEUE_MAX_SIZE)) return(STEREO_QUEUE_MAX_CHOICE);  if ((chans > 1) && (size < STEREO_QUEUE_MIN_SIZE)) return(STEREO_QUEUE_MIN_CHOICE);  return(size);}static void check_quad(int device, int channels){  long sr[2];  /* if quad, make sure we are set up for it, else make sure we aren't (perhaps the latter is unnecessary) */  /* in 4 channel mode, stereo mic and line-in are 4 inputs, headphones/speakers and stereo line-out are the 4 outputs */  sr[0] = AL_CHANNEL_MODE;  ALgetparams(device, sr, 2);  if ((channels == 4) && (sr[1] != AL_4CHANNEL))    {      sr[1] = AL_4CHANNEL;      ALsetparams(device, sr, 2);    }  else    {      if ((channels != 4) && (sr[1] != AL_STEREO))        {          sr[1] = AL_STEREO;          ALsetparams(device, sr, 2);        }    }}#endif#define IO_LINES 8static ALconfig *config = NULL;static ALport *port = NULL;static int *line_in_use = NULL;static int *channels = NULL;static long *device = NULL;static int *datum_size = NULL;static int *line_out = NULL;int mus_audio_initialize(void){  if (!audio_initialized)    {      audio_initialized = true;      config = (ALconfig *)CALLOC(IO_LINES, sizeof(ALconfig));      port = (ALport *)CALLOC(IO_LINES, sizeof(ALport));      line_in_use = (int *)CALLOC(IO_LINES, sizeof(int));      channels = (int *)CALLOC(IO_LINES, sizeof(int));

⌨️ 快捷键说明

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