/[qemu]/qemu/audio/audio.c
ViewVC logotype

Diff of /qemu/audio/audio.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.8 by bellard, Fri Nov 11 00:04:19 2005 UTC revision 1.9 by bellard, Sun Nov 20 16:24:34 2005 UTC
# Line 96  static struct { Line 96  static struct {
96    
97      { 0 },                      /* period */      { 0 },                      /* period */
98      0,                          /* plive */      0,                          /* plive */
99      0      0                           /* log_to_monitor */
100  };  };
101    
102  static AudioState glob_audio_state;  static AudioState glob_audio_state;
# Line 623  void audio_pcm_info_clear_buf (struct au Line 623  void audio_pcm_info_clear_buf (struct au
623  /*  /*
624   * Hard voice (capture)   * Hard voice (capture)
625   */   */
 static void audio_pcm_hw_free_resources_in (HWVoiceIn *hw)  
 {  
     if (hw->conv_buf) {  
         qemu_free (hw->conv_buf);  
     }  
     hw->conv_buf = NULL;  
 }  
   
 static int audio_pcm_hw_alloc_resources_in (HWVoiceIn *hw)  
 {  
     hw->conv_buf = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t));  
     if (!hw->conv_buf) {  
         dolog ("Could not allocate ADC conversion buffer (%d samples)\n",  
                hw->samples);  
         return -1;  
     }  
     return 0;  
 }  
   
626  static int audio_pcm_hw_find_min_in (HWVoiceIn *hw)  static int audio_pcm_hw_find_min_in (HWVoiceIn *hw)
627  {  {
628      SWVoiceIn *sw;      SWVoiceIn *sw;
# Line 668  int audio_pcm_hw_get_live_in (HWVoiceIn Line 649  int audio_pcm_hw_get_live_in (HWVoiceIn
649  /*  /*
650   * Soft voice (capture)   * Soft voice (capture)
651   */   */
 static void audio_pcm_sw_free_resources_in (SWVoiceIn *sw)  
 {  
     if (sw->conv_buf) {  
         qemu_free (sw->conv_buf);  
     }  
   
     if (sw->rate) {  
         st_rate_stop (sw->rate);  
     }  
   
     sw->conv_buf = NULL;  
     sw->rate = NULL;  
 }  
   
 static int audio_pcm_sw_alloc_resources_in (SWVoiceIn *sw)  
 {  
     int samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;  
     sw->conv_buf = audio_calloc (AUDIO_FUNC, samples, sizeof (st_sample_t));  
     if (!sw->conv_buf) {  
         dolog ("Could not allocate buffer for `%s' (%d samples)\n",  
                SW_NAME (sw), samples);  
         return -1;  
     }  
   
     sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);  
     if (!sw->rate) {  
         qemu_free (sw->conv_buf);  
         sw->conv_buf = NULL;  
         return -1;  
     }  
     return 0;  
 }  
   
 static int audio_pcm_sw_init_in (  
     SWVoiceIn *sw,  
     HWVoiceIn *hw,  
     const char *name,  
     audsettings_t *as  
     )  
 {  
     /* None of the cards emulated by QEMU are big-endian  
        hence following shortcut */  
     audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (0));  
     sw->hw = hw;  
     sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;  
   
     sw->clip =  
         mixeng_clip  
         [sw->info.nchannels == 2]  
         [sw->info.sign]  
         [sw->info.swap_endian]  
         [sw->info.bits == 16];  
   
     sw->name = qemu_strdup (name);  
     audio_pcm_sw_free_resources_in (sw);  
     return audio_pcm_sw_alloc_resources_in (sw);  
 }  
   
652  static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw)  static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw)
653  {  {
654      HWVoiceIn *hw = sw->hw;      HWVoiceIn *hw = sw->hw;
# Line 750  int audio_pcm_sw_read (SWVoiceIn *sw, vo Line 673  int audio_pcm_sw_read (SWVoiceIn *sw, vo
673  {  {
674      HWVoiceIn *hw = sw->hw;      HWVoiceIn *hw = sw->hw;
675      int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;      int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
676      st_sample_t *src, *dst = sw->conv_buf;      st_sample_t *src, *dst = sw->buf;
677    
678      rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;      rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
679    
# Line 794  int audio_pcm_sw_read (SWVoiceIn *sw, vo Line 717  int audio_pcm_sw_read (SWVoiceIn *sw, vo
717          total += isamp;          total += isamp;
718      }      }
719    
720      sw->clip (buf, sw->conv_buf, ret);      sw->clip (buf, sw->buf, ret);
721      sw->total_hw_samples_acquired += total;      sw->total_hw_samples_acquired += total;
722      return ret << sw->info.shift;      return ret << sw->info.shift;
723  }  }
# Line 802  int audio_pcm_sw_read (SWVoiceIn *sw, vo Line 725  int audio_pcm_sw_read (SWVoiceIn *sw, vo
725  /*  /*
726   * Hard voice (playback)   * Hard voice (playback)
727   */   */
 static void audio_pcm_hw_free_resources_out (HWVoiceOut *hw)  
 {  
     if (hw->mix_buf) {  
         qemu_free (hw->mix_buf);  
     }  
   
     hw->mix_buf = NULL;  
 }  
   
 static int audio_pcm_hw_alloc_resources_out (HWVoiceOut *hw)  
 {  
     hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t));  
     if (!hw->mix_buf) {  
         dolog ("Could not allocate DAC mixing buffer (%d samples)\n",  
                hw->samples);  
         return -1;  
     }  
   
     return 0;  
 }  
   
728  static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)  static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
729  {  {
730      SWVoiceOut *sw;      SWVoiceOut *sw;
# Line 876  int audio_pcm_hw_get_live_out (HWVoiceOu Line 778  int audio_pcm_hw_get_live_out (HWVoiceOu
778  /*  /*
779   * Soft voice (playback)   * Soft voice (playback)
780   */   */
 static void audio_pcm_sw_free_resources_out (SWVoiceOut *sw)  
 {  
     if (sw->buf) {  
         qemu_free (sw->buf);  
     }  
   
     if (sw->rate) {  
         st_rate_stop (sw->rate);  
     }  
   
     sw->buf = NULL;  
     sw->rate = NULL;  
 }  
   
 static int audio_pcm_sw_alloc_resources_out (SWVoiceOut *sw)  
 {  
     sw->buf = audio_calloc (AUDIO_FUNC, sw->hw->samples, sizeof (st_sample_t));  
     if (!sw->buf) {  
         dolog ("Could not allocate buffer for `%s' (%d samples)\n",  
                SW_NAME (sw), sw->hw->samples);  
         return -1;  
     }  
   
     sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);  
     if (!sw->rate) {  
         qemu_free (sw->buf);  
         sw->buf = NULL;  
         return -1;  
     }  
     return 0;  
 }  
   
 static int audio_pcm_sw_init_out (  
     SWVoiceOut *sw,  
     HWVoiceOut *hw,  
     const char *name,  
     audsettings_t *as  
     )  
 {  
     /* None of the cards emulated by QEMU are big-endian  
        hence following shortcut */  
     audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (0));  
     sw->hw = hw;  
     sw->empty = 1;  
     sw->active = 0;  
     sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;  
     sw->total_hw_samples_mixed = 0;  
   
     sw->conv =  
         mixeng_conv  
         [sw->info.nchannels == 2]  
         [sw->info.sign]  
         [sw->info.swap_endian]  
         [sw->info.bits == 16];  
     sw->name = qemu_strdup (name);  
   
     audio_pcm_sw_free_resources_out (sw);  
     return audio_pcm_sw_alloc_resources_out (sw);  
 }  
   
781  int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)  int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
782  {  {
783      int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;      int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
# Line 1316  static void audio_run_in (AudioState *s) Line 1158  static void audio_run_in (AudioState *s)
1158      }      }
1159  }  }
1160    
1161    static void audio_timer (void *opaque)
1162    {
1163        AudioState *s = opaque;
1164    
1165        audio_run_out (s);
1166        audio_run_in (s);
1167    
1168        qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
1169    }
1170    
1171  static struct audio_option audio_options[] = {  static struct audio_option audio_options[] = {
1172      /* DAC */      /* DAC */
1173      {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled,      {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled,
# Line 1356  static struct audio_option audio_options Line 1208  static struct audio_option audio_options
1208      {"PLIVE", AUD_OPT_BOOL, &conf.plive,      {"PLIVE", AUD_OPT_BOOL, &conf.plive,
1209       "(undocumented)", NULL, 0},       "(undocumented)", NULL, 0},
1210    
   
1211      {"LOG_TO_MONITOR", AUD_OPT_BOOL, &conf.log_to_monitor,      {"LOG_TO_MONITOR", AUD_OPT_BOOL, &conf.log_to_monitor,
1212       "print logging messages to montior instead of stderr", NULL, 0},       "print logging messages to montior instead of stderr", NULL, 0},
1213    
1214      {NULL, 0, NULL, NULL, NULL, 0}      {NULL, 0, NULL, NULL, NULL, 0}
1215  };  };
1216    
1217    static void audio_pp_nb_voices (const char *typ, int nb)
1218    {
1219        switch (nb) {
1220        case 0:
1221            printf ("Does not support %s\n", typ);
1222            break;
1223        case 1:
1224            printf ("One %s voice\n", typ);
1225            break;
1226        case INT_MAX:
1227            printf ("Theoretically supports many %s voices\n", typ);
1228            break;
1229        default:
1230            printf ("Theoretically supports upto %d %s voices\n", nb, typ);
1231            break;
1232        }
1233    
1234    }
1235    
1236  void AUD_help (void)  void AUD_help (void)
1237  {  {
1238      size_t i;      size_t i;
# Line 1387  void AUD_help (void) Line 1257  void AUD_help (void)
1257          printf ("Name: %s\n", d->name);          printf ("Name: %s\n", d->name);
1258          printf ("Description: %s\n", d->descr);          printf ("Description: %s\n", d->descr);
1259    
1260          switch (d->max_voices_out) {          audio_pp_nb_voices ("playback", d->max_voices_out);
1261          case 0:          audio_pp_nb_voices ("capture", d->max_voices_in);
             printf ("Does not support DAC\n");  
             break;  
         case 1:  
             printf ("One DAC voice\n");  
             break;  
         case INT_MAX:  
             printf ("Theoretically supports many DAC voices\n");  
             break;  
         default:  
             printf ("Theoretically supports upto %d DAC voices\n",  
                      d->max_voices_out);  
             break;  
         }  
   
         switch (d->max_voices_in) {  
         case 0:  
             printf ("Does not support ADC\n");  
             break;  
         case 1:  
             printf ("One ADC voice\n");  
             break;  
         case INT_MAX:  
             printf ("Theoretically supports many ADC voices\n");  
             break;  
         default:  
             printf ("Theoretically supports upto %d ADC voices\n",  
                      d->max_voices_in);  
             break;  
         }  
1262    
1263          if (d->options) {          if (d->options) {
1264              printf ("Options:\n");              printf ("Options:\n");
# Line 1434  void AUD_help (void) Line 1275  void AUD_help (void)
1275          "Example:\n"          "Example:\n"
1276  #ifdef _WIN32  #ifdef _WIN32
1277          "  set QEMU_AUDIO_DRV=wav\n"          "  set QEMU_AUDIO_DRV=wav\n"
1278          "  set QEMU_WAV_PATH=c:/tune.wav\n"          "  set QEMU_WAV_PATH=c:\\tune.wav\n"
1279  #else  #else
1280          "  export QEMU_AUDIO_DRV=wav\n"          "  export QEMU_AUDIO_DRV=wav\n"
1281          "  export QEMU_WAV_PATH=$HOME/tune.wav\n"          "  export QEMU_WAV_PATH=$HOME/tune.wav\n"
# Line 1444  void AUD_help (void) Line 1285  void AUD_help (void)
1285          );          );
1286  }  }
1287    
 void audio_timer (void *opaque)  
 {  
     AudioState *s = opaque;  
   
     audio_run_out (s);  
     audio_run_in (s);  
   
     qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);  
 }  
   
1288  static int audio_driver_init (AudioState *s, struct audio_driver *drv)  static int audio_driver_init (AudioState *s, struct audio_driver *drv)
1289  {  {
1290      if (drv->options) {      if (drv->options) {
# Line 1462  static int audio_driver_init (AudioState Line 1293  static int audio_driver_init (AudioState
1293      s->drv_opaque = drv->init ();      s->drv_opaque = drv->init ();
1294    
1295      if (s->drv_opaque) {      if (s->drv_opaque) {
1296          if (s->nb_hw_voices_out > drv->max_voices_out) {          audio_init_nb_voices_out (s, drv);
1297              if (!drv->max_voices_out) {          audio_init_nb_voices_in (s, drv);
                 dolog ("`%s' does not support DAC\n", drv->name);  
             }  
             else {  
                 dolog (  
                     "`%s' does not support %d multiple DAC voicess\n"  
                     "Resetting to %d\n",  
                     drv->name,  
                     s->nb_hw_voices_out,  
                     drv->max_voices_out  
                     );  
             }  
             s->nb_hw_voices_out = drv->max_voices_out;  
         }  
   
   
         if (!drv->voice_size_in && drv->max_voices_in) {  
             ldebug ("warning: No ADC voice size defined for `%s'\n",  
                     drv->name);  
             drv->max_voices_in = 0;  
         }  
   
         if (!drv->voice_size_out && drv->max_voices_out) {  
             ldebug ("warning: No DAC voice size defined for `%s'\n",  
                     drv->name);  
         }  
   
         if (drv->voice_size_in && !drv->max_voices_in) {  
             ldebug ("warning: `%s' ADC voice size %d, zero voices \n",  
                     drv->name, drv->voice_size_out);  
         }  
   
         if (drv->voice_size_out && !drv->max_voices_out) {  
             ldebug ("warning: `%s' DAC voice size %d, zero voices \n",  
                     drv->name, drv->voice_size_in);  
         }  
   
         if (s->nb_hw_voices_in > drv->max_voices_in) {  
             if (!drv->max_voices_in) {  
                 ldebug ("`%s' does not support ADC\n", drv->name);  
             }  
             else {  
                 dolog (  
                     "`%s' does not support %d multiple ADC voices\n"  
                     "Resetting to %d\n",  
                     drv->name,  
                     s->nb_hw_voices_in,  
                     drv->max_voices_in  
                     );  
             }  
             s->nb_hw_voices_in = drv->max_voices_in;  
         }  
   
         LIST_INIT (&s->hw_head_out);  
         LIST_INIT (&s->hw_head_in);  
1298          s->drv = drv;          s->drv = drv;
1299          return 0;          return 0;
1300      }      }
# Line 1549  static void audio_atexit (void) Line 1326  static void audio_atexit (void)
1326      HWVoiceOut *hwo = NULL;      HWVoiceOut *hwo = NULL;
1327      HWVoiceIn *hwi = NULL;      HWVoiceIn *hwi = NULL;
1328    
1329      while ((hwo = audio_pcm_hw_find_any_out (s, hwo))) {      while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
1330          if (!hwo->pcm_ops) {          hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
             continue;  
         }  
   
         if (hwo->enabled) {  
             hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);  
         }  
1331          hwo->pcm_ops->fini_out (hwo);          hwo->pcm_ops->fini_out (hwo);
1332      }      }
1333    
1334      while ((hwi = audio_pcm_hw_find_any_in (s, hwi))) {      while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
1335          if (!hwi->pcm_ops) {          hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
             continue;  
         }  
   
         if (hwi->enabled) {  
             hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);  
         }  
1336          hwi->pcm_ops->fini_in (hwi);          hwi->pcm_ops->fini_in (hwi);
1337      }      }
1338    
# Line 1616  AudioState *AUD_init (void) Line 1381  AudioState *AUD_init (void)
1381      const char *drvname;      const char *drvname;
1382      AudioState *s = &glob_audio_state;      AudioState *s = &glob_audio_state;
1383    
1384        LIST_INIT (&s->hw_head_out);
1385        LIST_INIT (&s->hw_head_in);
1386        atexit (audio_atexit);
1387    
1388        s->ts = qemu_new_timer (vm_clock, audio_timer, s);
1389        if (!s->ts) {
1390            dolog ("Could not create audio timer\n");
1391            return NULL;
1392        }
1393    
1394      audio_process_options ("AUDIO", audio_options);      audio_process_options ("AUDIO", audio_options);
1395    
1396      s->nb_hw_voices_out = conf.fixed_out.nb_voices;      s->nb_hw_voices_out = conf.fixed_out.nb_voices;
1397      s->nb_hw_voices_in = conf.fixed_in.nb_voices;      s->nb_hw_voices_in = conf.fixed_in.nb_voices;
1398    
1399      if (s->nb_hw_voices_out <= 0) {      if (s->nb_hw_voices_out <= 0) {
1400          dolog ("Bogus number of DAC voices %d\n",          dolog ("Bogus number of playback voices %d, setting to 1\n",
1401                 s->nb_hw_voices_out);                 s->nb_hw_voices_out);
1402          s->nb_hw_voices_out = 1;          s->nb_hw_voices_out = 1;
1403      }      }
1404    
1405      if (s->nb_hw_voices_in <= 0) {      if (s->nb_hw_voices_in <= 0) {
1406          dolog ("Bogus number of ADC voices %d\n",          dolog ("Bogus number of capture voices %d, setting to 0\n",
1407                 s->nb_hw_voices_in);                 s->nb_hw_voices_in);
1408          s->nb_hw_voices_in = 1;          s->nb_hw_voices_in = 0;
1409      }      }
1410    
1411      {      {
# Line 1638  AudioState *AUD_init (void) Line 1413  AudioState *AUD_init (void)
1413          drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def);          drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def);
1414      }      }
1415    
     s->ts = qemu_new_timer (vm_clock, audio_timer, s);  
     if (!s->ts) {  
         dolog ("Could not create audio timer\n");  
         return NULL;  
     }  
   
1416      if (drvname) {      if (drvname) {
1417          int found = 0;          int found = 0;
1418    
# Line 1680  AudioState *AUD_init (void) Line 1449  AudioState *AUD_init (void)
1449      }      }
1450    
1451      if (done) {      if (done) {
1452            VMChangeStateEntry *e;
1453    
1454          if (conf.period.hz <= 0) {          if (conf.period.hz <= 0) {
1455              if (conf.period.hz < 0) {              if (conf.period.hz < 0) {
1456                  dolog ("warning: Timer period is negative - %d "                  dolog ("warning: Timer period is negative - %d "
# Line 1692  AudioState *AUD_init (void) Line 1463  AudioState *AUD_init (void)
1463              conf.period.ticks = ticks_per_sec / conf.period.hz;              conf.period.ticks = ticks_per_sec / conf.period.hz;
1464          }          }
1465    
1466          qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);          e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
1467            if (!e) {
1468                dolog ("warning: Could not register change state handler\n"
1469                       "(Audio can continue looping even after stopping the VM)\n");
1470            }
1471      }      }
1472      else {      else {
1473          qemu_del_timer (s->ts);          qemu_del_timer (s->ts);
# Line 1701  AudioState *AUD_init (void) Line 1476  AudioState *AUD_init (void)
1476    
1477      LIST_INIT (&s->card_head);      LIST_INIT (&s->card_head);
1478      register_savevm ("audio", 0, 1, audio_save, audio_load, s);      register_savevm ("audio", 0, 1, audio_save, audio_load, s);
     atexit (audio_atexit);  
1479      qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);      qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
1480      return s;      return s;
1481  }  }

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.9

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26