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

📄 audio_config.c

📁 基于linux的DVD播放器程序
💻 C
字号:
/* Ogle - A video player * Copyright (C) 2002 Bj鰎n Englund, H錵an Hjort * * 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 */#include <stdio.h>#include <string.h>#include "audio_types.h"#include "parse_config.h"#include "audio_config.h"#include "sync.h"#include "debug_print.h"audio_config_t *audio_config_init(void){  audio_config_t *conf;  char *type;  int ms_offset;    conf = malloc(sizeof(audio_config_t));  memset(conf, 0, sizeof(audio_config_t));    conf->dst_format.nr_channels = -1;  conf->dst_format.ch_array = NULL;  conf->adev_handle = NULL;  conf->ainfo = NULL;    conf->sync.delay_resolution = 0;  conf->sync.delay_resolution_set = 0;  conf->sync.max_sync_diff = 0;  conf->sync.prev_delay = -1;  conf->sync.samples_added = 0;  type = get_sync_type();  if(!strcmp(type, "clock")) {    conf->sync.type = SyncType_clock;  } else {    conf->sync.type = SyncType_odelay;  }  conf->sync.resample = get_sync_resample();  ms_offset = get_sync_offset();  if(ms_offset > 999 || ms_offset < -999) {    ms_offset = 0;  }  TIME_S(conf->sync.offset) = 0;  TIME_SS(conf->sync.offset) = ms_offset * CT_FRACTION/1000;  return conf;}channel_config_t *get_config(ChannelType_t chtypemask_wanted){  channel_config_t *configs;  int nr_configs;  channel_config_t *chconf = NULL;  int n;  ChannelType_t chtypemask_avail = 0;  nr_configs = get_channel_configs(&configs);    DNOTE("%s", "Searching <speakers> for:\n");  if(chtypemask_wanted & ChannelTypeMask_Channels) {    DNOTE("%s", "");    for(n = 1; n <= 0x100; n = n << 1) {      if(n & chtypemask_wanted) {	DNOTEC(" '%s'", channeltype_str(n));      }    }    DNOTEC("%s", "\n");    if(chtypemask_wanted & ChannelTypeMask_Streams) {      DNOTE("%s", "or for:\n");    }  }  if(chtypemask_wanted & ChannelTypeMask_Streams) {    DNOTE(" '%s'",	  channeltype_str(chtypemask_wanted & ChannelTypeMask_Streams));  }  DNOTEC("%s", "\n");    for(n = 0; n < nr_configs; n++) {    int m;    int nr_ch;        chtypemask_avail = 0;    nr_ch = configs[n].nr_ch;    DNOTE("%s", "<channel_config>\n");    for(m = 0; m < nr_ch; m++) {      chtypemask_avail |= configs[n].chtype[m];      DNOTE("  <chtype>%s</chtype>\n", channeltype_str(configs[n].chtype[m]));    }    DNOTE("%s", "</channel_config>\n");    /* Want some channel based format, check if we can output that. */    if(chtypemask_wanted & ChannelTypeMask_Channels) {      if((chtypemask_wanted & chtypemask_avail) ==	 (chtypemask_wanted & ChannelTypeMask_Channels)) {	chconf = &configs[n];	DNOTE("%s", "Found matching channel_config\n");	break;      }    }    /* Want some stream based format, check if it matches. */    if(chtypemask_wanted & ChannelTypeMask_Streams) {      if((chtypemask_wanted & chtypemask_avail) ==	 (chtypemask_wanted & ChannelTypeMask_Streams)) {	chconf = &configs[n];	DNOTE("%s", "Found matching channel_config\n");	break;      }    }  }  if((!chconf) && (nr_configs > 0)) {    chconf = &configs[nr_configs-1];    DNOTE("%s", "Didn't find matching channel_config, using the last one\n");  } else if(nr_configs == 0) {    DNOTE("%s", "No channel configs found\n");  }    return chconf;}void free_config(channel_config_t *conf){  return;  if(conf) {    if(conf->chtype) {      free(conf->chtype);    }    free(conf);  }  return;}int audio_config(audio_config_t *aconf,		 ChannelType_t src_chtypemask,		 int sample_rate, int sample_resolution){  int n;  int output_channels;  int frag_size = 4096;  ogle_ao_encoding_t encoding;  channel_config_t *config = NULL;  // returns NULL if no config  // returns first config covering the requested chtypemask  // returns last config if no covering config found  // free_config should be called when config not needed more  config = get_config(src_chtypemask);  if(config) {    if((config->nr_ch > 0) && (config->chtype[0] & ChannelTypeMask_Streams)) {      if(config->chtype[0] == ChannelType_AC3) {	aconf->dst_format.sample_resolution = 0; //not used	aconf->dst_format.nr_channels = 2;	aconf->dst_format.ch_array = 	  realloc(aconf->dst_format.ch_array, 		  sizeof(ChannelType_t) * 2);	aconf->dst_format.ch_array[0] = ChannelType_AC3;	aconf->dst_format.ch_array[1] = ChannelType_AC3;	aconf->dst_format.sample_format = SampleFormat_IEC61937;      } else if(config->chtype[0] == ChannelType_DTS) {	aconf->dst_format.sample_resolution = 2;	aconf->dst_format.nr_channels = 2;	aconf->dst_format.ch_array = 	  realloc(aconf->dst_format.ch_array, 		  sizeof(ChannelType_t) * 2);	aconf->dst_format.ch_array[0] = ChannelType_DTS;	aconf->dst_format.ch_array[1] = ChannelType_DTS;	aconf->dst_format.sample_format = SampleFormat_IEC61937;      } else {	FATAL("channel type: %d not implemented\n", config->chtype[0]);      }    } else {      aconf->dst_format.sample_format = SampleFormat_Signed;      output_channels = config->nr_ch;      if(aconf->dst_format.nr_channels != output_channels) {	aconf->dst_format.ch_array = 	  realloc(aconf->dst_format.ch_array, 		  sizeof(ChannelType_t) * output_channels);      }      aconf->dst_format.sample_resolution = sample_resolution;      aconf->dst_format.nr_channels = output_channels;      for(n = 0; n < output_channels; n++) {	aconf->dst_format.ch_array[n] = config->chtype[n];      }    }  } else {    aconf->dst_format.sample_format = SampleFormat_Signed;    aconf->dst_format.sample_resolution = sample_resolution;    aconf->dst_format.nr_channels = 0;    if(aconf->dst_format.ch_array) {      free(aconf->dst_format.ch_array);      aconf->dst_format.ch_array = NULL;    }  }      {    ao_driver_t *drivers;        drivers = ao_drivers();    if(!aconf->adev_handle) {      int n;      int driver_n = 0;      char *driver_str = get_audio_driver();            if(driver_str != NULL) {	for(n = 0; drivers[n].name != NULL; n++) {	  if(!strcmp(drivers[n].name, driver_str)) {	    driver_n = n;	    break;	  }	}	if(drivers[n].name == NULL) {	  NOTE("Audio driver '%s' not found\n", driver_str);	}      }      NOTE("Using audio driver '%s'\n", drivers[driver_n].name);	           if(drivers[driver_n].open != NULL) {	char *dev_string;	if(!strcmp("alsa", drivers[driver_n].name)) {	  dev_string = get_audio_alsa_name();	} else {	  dev_string = get_audio_device();	}	aconf->adev_handle = ogle_ao_open(drivers[driver_n].open, dev_string);	if(!aconf->adev_handle) {	  FATAL("failed opening the %s audio driver at %s\n",		drivers[driver_n].name, dev_string);	  exit(1);	}      } else {	FATAL("%s", "ogle_ao_open not taken, no audio ouput driver!\n");	exit(1);      }    }    // DNOTE("%s", "ogle_ao_open passed\n");  }  if(!aconf->ainfo) {    aconf->ainfo = malloc(sizeof(ogle_ao_audio_info_t));    aconf->ainfo->chlist = NULL;  }  if(aconf->dst_format.sample_format == SampleFormat_IEC61937) {    aconf->ainfo->sample_rate = sample_rate;    aconf->ainfo->sample_resolution = sample_resolution;    aconf->ainfo->byteorder = OGLE_AO_BYTEORDER_NE;    aconf->ainfo->channels = aconf->dst_format.nr_channels;    encoding = OGLE_AO_ENCODING_IEC61937;    aconf->ainfo->fragment_size = frag_size;    aconf->ainfo->fragments = -1;  // don't limit  } else {        aconf->ainfo->sample_rate = sample_rate;    aconf->ainfo->sample_resolution = sample_resolution;    aconf->ainfo->byteorder = OGLE_AO_BYTEORDER_NE;    aconf->ainfo->channels = aconf->dst_format.nr_channels;    encoding = OGLE_AO_ENCODING_LINEAR;    aconf->ainfo->fragment_size = frag_size;    aconf->ainfo->fragments = -1;  // don't limit    if(config) {      aconf->ainfo->chtypes = OGLE_AO_CHTYPE_UNSPECIFIED;    } else {      ogle_ao_chtype_t ao_chmask = 0;      if(src_chtypemask & ChannelType_Left) {	ao_chmask |= OGLE_AO_CHTYPE_LEFT;      }      if(src_chtypemask & ChannelType_Right) {	ao_chmask |= OGLE_AO_CHTYPE_RIGHT;      }      if(src_chtypemask & ChannelType_Center) {	ao_chmask |= OGLE_AO_CHTYPE_CENTER;      }      if(src_chtypemask & ChannelType_LeftSurround) {	ao_chmask |= OGLE_AO_CHTYPE_REARLEFT;      }      if(src_chtypemask & ChannelType_RightSurround) {	ao_chmask |= OGLE_AO_CHTYPE_REARRIGHT;      }      if(src_chtypemask & ChannelType_LFE) {	ao_chmask |= OGLE_AO_CHTYPE_LFE;      }      if(src_chtypemask & ChannelType_Mono) {	ao_chmask |= OGLE_AO_CHTYPE_MONO;      }      if(src_chtypemask & ChannelType_Surround) {	ao_chmask |= OGLE_AO_CHTYPE_REARMONO;      }      if(src_chtypemask & ChannelType_CenterSurround) {	ao_chmask |= OGLE_AO_CHTYPE_REARCENTER;      }            if(ao_chmask == 0) {	ao_chmask = OGLE_AO_CHTYPE_NULL;      }      aconf->ainfo->chtypes = ao_chmask;    }  }  aconf->ainfo->encoding = encoding;  // check return value  if(ogle_ao_init(aconf->adev_handle, aconf->ainfo) == -1) {    FATAL("%s", "ogle_ao_init: ");    if(aconf->ainfo->sample_rate == -1) {      FATALC("sample_rate %d failed", sample_rate);    } else if(aconf->ainfo->sample_resolution == -1 ||	      aconf->ainfo->encoding == -1 ||	      aconf->ainfo->byteorder == -1) {      FATALC("encoding %d, resolution %d, byte order %d failed",	    encoding, sample_resolution, OGLE_AO_BYTEORDER_NE);    } else if(aconf->ainfo->channels == -1) {      FATALC("channels %d failed", aconf->dst_format.nr_channels);    }     FATALC("%s", "\n");  } else {    if(aconf->ainfo->sample_rate != sample_rate) {      ERROR("wanted sample rate %d, got %d\n",	    sample_rate,	    aconf->ainfo->sample_rate);    }    if(aconf->ainfo->sample_resolution != sample_resolution) {      ERROR("wanted sample resolution %d, got %d\n",	    sample_resolution,	    aconf->ainfo->sample_resolution);	       }    if(aconf->ainfo->byteorder != OGLE_AO_BYTEORDER_NE) {      ERROR("wanted byte order %d, got %d\n",	    OGLE_AO_BYTEORDER_NE, aconf->ainfo->byteorder);    }    if(aconf->ainfo->channels != aconf->dst_format.nr_channels &&       aconf->dst_format.nr_channels != -1) {      NOTE("wanted %d channels, got %d\n",	   aconf->dst_format.nr_channels,	   aconf->ainfo->channels);       if(config) {	if((config->nr_ch > 0) && 	   (config->chtype[0] & ChannelTypeMask_Streams)) {	  	} else {	  output_channels = aconf->ainfo->channels;	  if(aconf->dst_format.nr_channels != output_channels) {	    aconf->dst_format.ch_array = 	      realloc(aconf->dst_format.ch_array, 		      sizeof(ChannelType_t) * output_channels);	  }	  aconf->dst_format.nr_channels = output_channels;	  for(n = 0; n < output_channels; n++) {	    if(n < config->nr_ch) {	      aconf->dst_format.ch_array[n] = config->chtype[n];	    } else {	      aconf->dst_format.ch_array[n] = ChannelType_Null;	    }	  }	}      }    }    if(aconf->ainfo->encoding != encoding) {      ERROR("wanted encoding %d, got %d\n",	    encoding,	    aconf->ainfo->encoding);      switch(aconf->ainfo->encoding) {      case OGLE_AO_ENCODING_IEC61937:	aconf->dst_format.sample_format = SampleFormat_IEC61937;	break;      case OGLE_AO_ENCODING_LINEAR:      default:		aconf->dst_format.sample_format = SampleFormat_Signed;	break;      }    }    if(frag_size != -1 && aconf->ainfo->fragment_size != frag_size) {      NOTE("wanted fragment size %d, got %d\n",	   frag_size,	   aconf->ainfo->fragment_size);    }    DNOTE("channels %d, encoding %d, resolution %d\n", 	  aconf->ainfo->channels,	  aconf->ainfo->encoding,	  aconf->ainfo->sample_resolution);    DNOTE("byte order %d, rate %d\n",	  aconf->ainfo->byteorder,	  aconf->ainfo->sample_rate);    DNOTE("fragments %d, size %d\n",	  aconf->ainfo->fragments,	  aconf->ainfo->fragment_size);    if(!config) {      aconf->dst_format.nr_channels = aconf->ainfo->channels;      aconf->dst_format.ch_array = 	realloc(aconf->dst_format.ch_array, 		sizeof(ChannelType_t)*aconf->dst_format.nr_channels);      for(n = 0; n < aconf->dst_format.nr_channels; n++) {	ChannelType_t ct;	switch(aconf->ainfo->chlist[n]) {	case OGLE_AO_CHTYPE_LEFT:	  ct = ChannelType_Left;	  break;	case OGLE_AO_CHTYPE_RIGHT:	  ct = ChannelType_Right;	  break;	case OGLE_AO_CHTYPE_CENTER:	  ct = ChannelType_Center;	  break;	case OGLE_AO_CHTYPE_REARLEFT:	  ct = ChannelType_LeftSurround;	  break;	case OGLE_AO_CHTYPE_REARRIGHT:	  ct = ChannelType_RightSurround;	  break;	case OGLE_AO_CHTYPE_LFE:	  ct = ChannelType_LFE;	  break;	case OGLE_AO_CHTYPE_MONO:	  ct = ChannelType_Mono;	  break;	case OGLE_AO_CHTYPE_REARCENTER:	  ct = ChannelType_CenterSurround;	  break;	case OGLE_AO_CHTYPE_REARMONO:	  ct = ChannelType_Surround;	  break;	default:	  DNOTE("unkown chtype: %d\n", aconf->ainfo->chlist[n]);	  ct = -1;	  break;	}	aconf->dst_format.ch_array[n] = ct;      }    }    aconf->dst_format.sample_resolution = aconf->ainfo->sample_resolution;  }  if(config) {    free_config(config);    config = NULL;  }  aconf->dst_format.sample_frame_size = aconf->ainfo->sample_frame_size;  aconf->sync.delay_resolution = aconf->ainfo->sample_rate / 10;  aconf->sync.delay_resolution_set = 0;  aconf->sync.max_sync_diff = 2 * aconf->sync.delay_resolution *    (CT_FRACTION / aconf->ainfo->sample_rate);  aconf->sync.prev_delay = -1;  aconf->sync.samples_added = 0;  return 0;}void audio_config_close(audio_config_t *aconf){    if(aconf != NULL) {    if(aconf->adev_handle != NULL) {      ogle_ao_close(aconf->adev_handle);      aconf->adev_handle = NULL;    }        if(aconf->dst_format.ch_array != NULL) {      free(aconf->dst_format.ch_array);      aconf->dst_format.ch_array = NULL;    }        free(aconf);  }  }

⌨️ 快捷键说明

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