/[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.6 by bellard, Sun Oct 30 18:58:22 2005 UTC revision 1.7 by bellard, Sat Nov 5 18:55:27 2005 UTC
# Line 26  Line 26 
26  #define AUDIO_CAP "audio"  #define AUDIO_CAP "audio"
27  #include "audio_int.h"  #include "audio_int.h"
28    
 static void audio_pcm_hw_fini_in (HWVoiceIn *hw);  
 static void audio_pcm_hw_fini_out (HWVoiceOut *hw);  
   
 static LIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in;  
 static LIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out;  
   
29  /* #define DEBUG_PLIVE */  /* #define DEBUG_PLIVE */
30  /* #define DEBUG_LIVE */  /* #define DEBUG_LIVE */
31  /* #define DEBUG_OUT */  /* #define DEBUG_OUT */
32    
33    #define SW_NAME(sw) (sw)->name ? (sw)->name : "unknown"
34    
35  static struct audio_driver *drvtab[] = {  static struct audio_driver *drvtab[] = {
36  #ifdef CONFIG_OSS  #ifdef CONFIG_OSS
37      &oss_audio_driver,      &oss_audio_driver,
# Line 59  static struct audio_driver *drvtab[] = { Line 55  static struct audio_driver *drvtab[] = {
55      &wav_audio_driver      &wav_audio_driver
56  };  };
57    
58  AudioState audio_state = {  struct fixed_settings {
59      /* Out */      int enabled;
60      1,                          /* use fixed settings */      int nb_voices;
61      44100,                      /* fixed frequency */      int greedy;
62      2,                          /* fixed channels */      audsettings_t settings;
63      AUD_FMT_S16,                /* fixed format */  };
     1,                          /* number of hw voices */  
     1,                          /* greedy */  
   
     /* In */  
     1,                          /* use fixed settings */  
     44100,                      /* fixed frequency */  
     2,                          /* fixed channels */  
     AUD_FMT_S16,                /* fixed format */  
     1,                          /* number of hw voices */  
     1,                          /* greedy */  
64    
65      NULL,                       /* driver opaque */  static struct {
66      NULL,                       /* driver */      struct fixed_settings fixed_out;
67        struct fixed_settings fixed_in;
68        union {
69            int hz;
70            int64_t ticks;
71        } period;
72        int plive;
73    } conf = {
74        {                           /* DAC fixed settings */
75            1,                      /* enabled */
76            1,                      /* nb_voices */
77            1,                      /* greedy */
78            {
79                44100,              /* freq */
80                2,                  /* nchannels */
81                AUD_FMT_S16         /* fmt */
82            }
83        },
84    
85        {                           /* ADC fixed settings */
86            1,                      /* enabled */
87            1,                      /* nb_voices */
88            1,                      /* greedy */
89            {
90                44100,              /* freq */
91                2,                  /* nchannels */
92                AUD_FMT_S16         /* fmt */
93            }
94        },
95    
     NULL,                       /* timer handle */  
96      { 0 },                      /* period */      { 0 },                      /* period */
97      0                           /* plive */      0                           /* plive */
98  };  };
99    
100    static AudioState glob_audio_state;
101    
102  volume_t nominal_volume = {  volume_t nominal_volume = {
103      0,      0,
104  #ifdef FLOAT_MIXENG  #ifdef FLOAT_MIXENG
# Line 148  int audio_bug (const char *funcname, int Line 163  int audio_bug (const char *funcname, int
163  }  }
164  #endif  #endif
165    
166    void *audio_calloc (const char *funcname, int nmemb, size_t size)
167    {
168        int cond;
169        size_t len;
170    
171        len = nmemb * size;
172        cond = !nmemb || !size;
173        cond |= nmemb < 0;
174        cond |= len < size;
175    
176        if (audio_bug ("audio_calloc", cond)) {
177            AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n",
178                     funcname);
179            AUD_log (NULL, "nmemb=%d size=%d (len=%d)\n", nmemb, size, len);
180            return NULL;
181        }
182    
183        return qemu_mallocz (len);
184    }
185    
186  static char *audio_alloc_prefix (const char *s)  static char *audio_alloc_prefix (const char *s)
187  {  {
188      const char qemu_prefix[] = "QEMU_";      const char qemu_prefix[] = "QEMU_";
# Line 386  static void audio_process_options (const Line 421  static void audio_process_options (const
421          }          }
422    
423          len = strlen (opt->name);          len = strlen (opt->name);
424            /* len of opt->name + len of prefix + size of qemu_prefix
425             * (includes trailing zero) + zero + underscore (on behalf of
426             * sizeof) */
427          optname = qemu_malloc (len + preflen + sizeof (qemu_prefix) + 1);          optname = qemu_malloc (len + preflen + sizeof (qemu_prefix) + 1);
428          if (!optname) {          if (!optname) {
429              dolog ("Can not allocate memory for option name `%s'\n",              dolog ("Could not allocate memory for option name `%s'\n",
430                     opt->name);                     opt->name);
431              continue;              continue;
432          }          }
433    
434          strcpy (optname, qemu_prefix);          strcpy (optname, qemu_prefix);
435    
436            /* copy while upper-casing, including trailing zero */
437          for (i = 0; i <= preflen; ++i) {          for (i = 0; i <= preflen; ++i) {
438              optname[i + sizeof (qemu_prefix) - 1] = toupper (prefix[i]);              optname[i + sizeof (qemu_prefix) - 1] = toupper (prefix[i]);
439          }          }
# Line 438  static void audio_process_options (const Line 478  static void audio_process_options (const
478      }      }
479  }  }
480    
481  static int audio_pcm_info_eq (struct audio_pcm_info *info, int freq,  static void audio_print_settings (audsettings_t *as)
482                                int nchannels, audfmt_e fmt)  {
483        dolog ("frequency=%d nchannels=%d fmt=", as->freq, as->nchannels);
484    
485        switch (as->fmt) {
486        case AUD_FMT_S8:
487            AUD_log (NULL, "S8");
488            break;
489        case AUD_FMT_U8:
490            AUD_log (NULL, "U8");
491            break;
492        case AUD_FMT_S16:
493            AUD_log (NULL, "S16");
494            break;
495        case AUD_FMT_U16:
496            AUD_log (NULL, "U16");
497            break;
498        default:
499            AUD_log (NULL, "invalid(%d)", as->fmt);
500            break;
501        }
502        AUD_log (NULL, "\n");
503    }
504    
505    static int audio_validate_settigs (audsettings_t *as)
506    {
507        int invalid;
508    
509        invalid = as->nchannels != 1 && as->nchannels != 2;
510    
511        switch (as->fmt) {
512        case AUD_FMT_S8:
513        case AUD_FMT_U8:
514        case AUD_FMT_S16:
515        case AUD_FMT_U16:
516            break;
517        default:
518            invalid = 1;
519            break;
520        }
521    
522        invalid |= as->freq <= 0;
523    
524        if (invalid) {
525            return -1;
526        }
527        return 0;
528    }
529    
530    static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
531  {  {
532      int bits = 8, sign = 0;      int bits = 8, sign = 0;
533    
534      switch (fmt) {      switch (as->fmt) {
535      case AUD_FMT_S8:      case AUD_FMT_S8:
536          sign = 1;          sign = 1;
537      case AUD_FMT_U8:      case AUD_FMT_U8:
# Line 455  static int audio_pcm_info_eq (struct aud Line 543  static int audio_pcm_info_eq (struct aud
543          bits = 16;          bits = 16;
544          break;          break;
545      }      }
546      return info->freq == freq      return info->freq == as->freq
547          && info->nchannels == nchannels          && info->nchannels == as->nchannels
548          && info->sign == sign          && info->sign == sign
549          && info->bits == bits;          && info->bits == bits;
550  }  }
551    
552  void audio_pcm_init_info (struct audio_pcm_info *info, int freq,  void audio_pcm_init_info (
553                            int nchannels, audfmt_e fmt, int swap_endian)      struct audio_pcm_info *info,
554        audsettings_t *as,
555        int swap_endian
556        )
557  {  {
558      int bits = 8, sign = 0;      int bits = 8, sign = 0;
559    
560      switch (fmt) {      switch (as->fmt) {
561      case AUD_FMT_S8:      case AUD_FMT_S8:
562          sign = 1;          sign = 1;
563      case AUD_FMT_U8:      case AUD_FMT_U8:
# Line 479  void audio_pcm_init_info (struct audio_p Line 570  void audio_pcm_init_info (struct audio_p
570          break;          break;
571      }      }
572    
573      info->freq = freq;      info->freq = as->freq;
574      info->bits = bits;      info->bits = bits;
575      info->sign = sign;      info->sign = sign;
576      info->nchannels = nchannels;      info->nchannels = as->nchannels;
577      info->shift = (nchannels == 2) + (bits == 16);      info->shift = (as->nchannels == 2) + (bits == 16);
578      info->align = (1 << info->shift) - 1;      info->align = (1 << info->shift) - 1;
579      info->bytes_per_second = info->freq << info->shift;      info->bytes_per_second = info->freq << info->shift;
580      info->swap_endian = swap_endian;      info->swap_endian = swap_endian;
# Line 532  static void audio_pcm_hw_free_resources_ Line 623  static void audio_pcm_hw_free_resources_
623    
624  static int audio_pcm_hw_alloc_resources_in (HWVoiceIn *hw)  static int audio_pcm_hw_alloc_resources_in (HWVoiceIn *hw)
625  {  {
626      hw->conv_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));      hw->conv_buf = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t));
627      if (!hw->conv_buf) {      if (!hw->conv_buf) {
628            dolog ("Could not allocate ADC conversion buffer (%d bytes)\n",
629                   hw->samples * sizeof (st_sample_t));
630          return -1;          return -1;
631      }      }
632      return 0;      return 0;
633  }  }
634    
635  static int audio_pcm_hw_init_in (HWVoiceIn *hw, int freq, int nchannels, audfmt_e fmt)  static int audio_pcm_hw_find_min_in (HWVoiceIn *hw)
 {  
     audio_pcm_hw_fini_in (hw);  
   
     if (hw->pcm_ops->init_in (hw, freq, nchannels, fmt)) {  
         memset (hw, 0, audio_state.drv->voice_size_in);  
         return -1;  
     }  
     LIST_INIT (&hw->sw_head);  
     hw->active = 1;  
     hw->samples = hw->bufsize >> hw->info.shift;  
     hw->conv =  
         mixeng_conv  
         [nchannels == 2]  
         [hw->info.sign]  
         [hw->info.swap_endian]  
         [hw->info.bits == 16];  
     if (audio_pcm_hw_alloc_resources_in (hw)) {  
         audio_pcm_hw_free_resources_in (hw);  
         return -1;  
     }  
     return 0;  
 }  
   
 static uint64_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)  
636  {  {
637      SWVoiceIn *sw;      SWVoiceIn *sw;
638      int m = hw->total_samples_captured;      int m = hw->total_samples_captured;
# Line 606  static void audio_pcm_sw_free_resources_ Line 675  static void audio_pcm_sw_free_resources_
675  static int audio_pcm_sw_alloc_resources_in (SWVoiceIn *sw)  static int audio_pcm_sw_alloc_resources_in (SWVoiceIn *sw)
676  {  {
677      int samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;      int samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
678      sw->conv_buf = qemu_mallocz (samples * sizeof (st_sample_t));      sw->conv_buf = audio_calloc (AUDIO_FUNC, samples, sizeof (st_sample_t));
679      if (!sw->conv_buf) {      if (!sw->conv_buf) {
680            dolog ("Could not allocate buffer for `%s' (%d bytes)\n",
681                   SW_NAME (sw), samples * sizeof (st_sample_t));
682          return -1;          return -1;
683      }      }
684    
# Line 620  static int audio_pcm_sw_alloc_resources_ Line 691  static int audio_pcm_sw_alloc_resources_
691      return 0;      return 0;
692  }  }
693    
694  static int audio_pcm_sw_init_in (SWVoiceIn *sw, HWVoiceIn *hw, const char *name,  static int audio_pcm_sw_init_in (
695                             int freq, int nchannels, audfmt_e fmt)      SWVoiceIn *sw,
696  {      HWVoiceIn *hw,
697      audio_pcm_init_info (&sw->info, freq, nchannels, fmt,      const char *name,
698                           /* None of the cards emulated by QEMU are big-endian      audsettings_t *as
699                              hence following shortcut */      )
700                           audio_need_to_swap_endian (0));  {
701        /* None of the cards emulated by QEMU are big-endian
702           hence following shortcut */
703        audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (0));
704      sw->hw = hw;      sw->hw = hw;
705      sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;      sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
706    
707      sw->clip =      sw->clip =
708          mixeng_clip          mixeng_clip
709          [nchannels == 2]          [sw->info.nchannels == 2]
710          [sw->info.sign]          [sw->info.sign]
711          [sw->info.swap_endian]          [sw->info.swap_endian]
712          [sw->info.bits == 16];          [sw->info.bits == 16];
# Line 699  int audio_pcm_sw_read (SWVoiceIn *sw, vo Line 773  int audio_pcm_sw_read (SWVoiceIn *sw, vo
773    
774          if (audio_bug (AUDIO_FUNC, osamp < 0)) {          if (audio_bug (AUDIO_FUNC, osamp < 0)) {
775              dolog ("osamp=%d\n", osamp);              dolog ("osamp=%d\n", osamp);
776                return 0;
777          }          }
778    
779          st_rate_flow (sw->rate, src, dst, &isamp, &osamp);          st_rate_flow (sw->rate, src, dst, &isamp, &osamp);
# Line 717  int audio_pcm_sw_read (SWVoiceIn *sw, vo Line 792  int audio_pcm_sw_read (SWVoiceIn *sw, vo
792  /*  /*
793   * Hard voice (playback)   * Hard voice (playback)
794   */   */
 static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)  
 {  
     SWVoiceOut *sw;  
     int m = INT_MAX;  
     int nb_live = 0;  
   
     for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {  
         if (sw->active || !sw->empty) {  
             m = audio_MIN (m, sw->total_hw_samples_mixed);  
             nb_live += 1;  
         }  
     }  
   
     *nb_livep = nb_live;  
     return m;  
 }  
   
795  static void audio_pcm_hw_free_resources_out (HWVoiceOut *hw)  static void audio_pcm_hw_free_resources_out (HWVoiceOut *hw)
796  {  {
797      if (hw->mix_buf) {      if (hw->mix_buf) {
# Line 745  static void audio_pcm_hw_free_resources_ Line 803  static void audio_pcm_hw_free_resources_
803    
804  static int audio_pcm_hw_alloc_resources_out (HWVoiceOut *hw)  static int audio_pcm_hw_alloc_resources_out (HWVoiceOut *hw)
805  {  {
806      hw->mix_buf = qemu_mallocz (hw->samples * sizeof (st_sample_t));      hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t));
807      if (!hw->mix_buf) {      if (!hw->mix_buf) {
808            dolog ("Could not allocate DAC mixing buffer (%d bytes)\n",
809                   hw->samples * sizeof (st_sample_t));
810          return -1;          return -1;
811      }      }
812    
813      return 0;      return 0;
814  }  }
815    
816  static int audio_pcm_hw_init_out (HWVoiceOut *hw, int freq,  static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
                             int nchannels, audfmt_e fmt)  
817  {  {
818      audio_pcm_hw_fini_out (hw);      SWVoiceOut *sw;
819      if (hw->pcm_ops->init_out (hw, freq, nchannels, fmt)) {      int m = INT_MAX;
820          memset (hw, 0, audio_state.drv->voice_size_out);      int nb_live = 0;
         return -1;  
     }  
821    
822      LIST_INIT (&hw->sw_head);      for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
823      hw->active = 1;          if (sw->active || !sw->empty) {
824      hw->samples = hw->bufsize >> hw->info.shift;              m = audio_MIN (m, sw->total_hw_samples_mixed);
825      hw->clip =              nb_live += 1;
826          mixeng_clip          }
         [nchannels == 2]  
         [hw->info.sign]  
         [hw->info.swap_endian]  
         [hw->info.bits == 16];  
     if (audio_pcm_hw_alloc_resources_out (hw)) {  
         audio_pcm_hw_fini_out (hw);  
         return -1;  
827      }      }
828      return 0;  
829        *nb_livep = nb_live;
830        return m;
831  }  }
832    
833  int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live)  int audio_pcm_hw_get_live_out2 (HWVoiceOut *hw, int *nb_live)
# Line 830  static void audio_pcm_sw_free_resources_ Line 882  static void audio_pcm_sw_free_resources_
882    
883  static int audio_pcm_sw_alloc_resources_out (SWVoiceOut *sw)  static int audio_pcm_sw_alloc_resources_out (SWVoiceOut *sw)
884  {  {
885      sw->buf = qemu_mallocz (sw->hw->samples * sizeof (st_sample_t));      sw->buf = audio_calloc (AUDIO_FUNC, sw->hw->samples, sizeof (st_sample_t));
886      if (!sw->buf) {      if (!sw->buf) {
887            dolog ("Could not allocate buffer for `%s' (%d bytes)\n",
888                   SW_NAME (sw), sw->hw->samples * sizeof (st_sample_t));
889          return -1;          return -1;
890      }      }
891    
# Line 844  static int audio_pcm_sw_alloc_resources_ Line 898  static int audio_pcm_sw_alloc_resources_
898      return 0;      return 0;
899  }  }
900    
901  static int audio_pcm_sw_init_out (SWVoiceOut *sw, HWVoiceOut *hw,  static int audio_pcm_sw_init_out (
902                              const char *name, int freq,      SWVoiceOut *sw,
903                              int nchannels, audfmt_e fmt)      HWVoiceOut *hw,
904  {      const char *name,
905      audio_pcm_init_info (&sw->info, freq, nchannels, fmt,      audsettings_t *as
906                           /* None of the cards emulated by QEMU are big-endian      )
907                              hence following shortcut */  {
908                           audio_need_to_swap_endian (0));      /* None of the cards emulated by QEMU are big-endian
909           hence following shortcut */
910        audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (0));
911      sw->hw = hw;      sw->hw = hw;
912      sw->empty = 1;      sw->empty = 1;
913      sw->active = 0;      sw->active = 0;
# Line 860  static int audio_pcm_sw_init_out (SWVoic Line 916  static int audio_pcm_sw_init_out (SWVoic
916    
917      sw->conv =      sw->conv =
918          mixeng_conv          mixeng_conv
919          [nchannels == 2]          [sw->info.nchannels == 2]
920          [sw->info.sign]          [sw->info.sign]
921          [sw->info.swap_endian]          [sw->info.swap_endian]
922          [sw->info.bits == 16];          [sw->info.bits == 16];
# Line 930  int audio_pcm_sw_write (SWVoiceOut *sw, Line 986  int audio_pcm_sw_write (SWVoiceOut *sw,
986    
987  #ifdef DEBUG_OUT  #ifdef DEBUG_OUT
988      dolog (      dolog (
989          "%s: write size %d ret %d total sw %d, hw %d\n",          "%s: write size %d ret %d total sw %d\n",
990          sw->name,          SW_NAME (sw),
991          size >> sw->info.shift,          size >> sw->info.shift,
992          ret,          ret,
993          sw->total_hw_samples_mixed,          sw->total_hw_samples_mixed
         sw->hw->total_samples_played  
994          );          );
995  #endif  #endif
996    
# Line 965  int AUD_write (SWVoiceOut *sw, void *buf Line 1020  int AUD_write (SWVoiceOut *sw, void *buf
1020      }      }
1021    
1022      if (!sw->hw->enabled) {      if (!sw->hw->enabled) {
1023          dolog ("Writing to disabled voice %s\n", sw->name);          dolog ("Writing to disabled voice %s\n", SW_NAME (sw));
1024          return 0;          return 0;
1025      }      }
1026    
# Line 983  int AUD_read (SWVoiceIn *sw, void *buf, Line 1038  int AUD_read (SWVoiceIn *sw, void *buf,
1038      }      }
1039    
1040      if (!sw->hw->enabled) {      if (!sw->hw->enabled) {
1041          dolog ("Reading from disabled voice %s\n", sw->name);          dolog ("Reading from disabled voice %s\n", SW_NAME (sw));
1042          return 0;          return 0;
1043      }      }
1044    
# Line 993  int AUD_read (SWVoiceIn *sw, void *buf, Line 1048  int AUD_read (SWVoiceIn *sw, void *buf,
1048    
1049  int AUD_get_buffer_size_out (SWVoiceOut *sw)  int AUD_get_buffer_size_out (SWVoiceOut *sw)
1050  {  {
1051      return sw->hw->bufsize;      return sw->hw->samples << sw->hw->info.shift;
1052  }  }
1053    
1054  void AUD_set_active_out (SWVoiceOut *sw, int on)  void AUD_set_active_out (SWVoiceOut *sw, int on)
# Line 1091  static int audio_get_avail (SWVoiceIn *s Line 1146  static int audio_get_avail (SWVoiceIn *s
1146    
1147      ldebug (      ldebug (
1148          "%s: get_avail live %d ret %lld\n",          "%s: get_avail live %d ret %lld\n",
1149          sw->name,          SW_NAME (sw),
1150          live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift          live, (((int64_t) live << 32) / sw->ratio) << sw->info.shift
1151          );          );
1152    
# Line 1110  static int audio_get_free (SWVoiceOut *s Line 1165  static int audio_get_free (SWVoiceOut *s
1165    
1166      if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {      if (audio_bug (AUDIO_FUNC, live < 0 || live > sw->hw->samples)) {
1167          dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);          dolog ("live=%d sw->hw->samples=%d\n", live, sw->hw->samples);
1168            return 0;
1169      }      }
1170    
1171      dead = sw->hw->samples - live;      dead = sw->hw->samples - live;
1172    
1173  #ifdef DEBUG_OUT  #ifdef DEBUG_OUT
1174      dolog ("%s: get_free live %d dead %d ret %lld\n",      dolog ("%s: get_free live %d dead %d ret %lld\n",
1175             sw->name,             SW_NAME (sw),
1176             live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);             live, dead, (((int64_t) dead << 32) / sw->ratio) << sw->info.shift);
1177  #endif  #endif
1178    
1179      return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;      return (((int64_t) dead << 32) / sw->ratio) << sw->info.shift;
1180  }  }
1181    
1182  static void audio_run_out (void)  static void audio_run_out (AudioState *s)
1183  {  {
1184      HWVoiceOut *hw = NULL;      HWVoiceOut *hw = NULL;
1185      SWVoiceOut *sw;      SWVoiceOut *sw;
1186    
1187      while ((hw = audio_pcm_hw_find_any_active_enabled_out (hw))) {      while ((hw = audio_pcm_hw_find_any_enabled_out (s, hw))) {
1188          int played;          int played;
1189          int live, free, nb_live;          int live, free, nb_live, cleanup_required;
1190    
1191          live = audio_pcm_hw_get_live_out2 (hw, &nb_live);          live = audio_pcm_hw_get_live_out2 (hw, &nb_live);
1192          if (!nb_live) {          if (!nb_live) {
1193              live = 0;              live = 0;
1194          }          }
1195    
1196          if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {          if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
1197              dolog ("live=%d hw->samples=%d\n", live, hw->samples);              dolog ("live=%d hw->samples=%d\n", live, hw->samples);
1198                continue;
1199          }          }
1200    
1201          if (hw->pending_disable && !nb_live) {          if (hw->pending_disable && !nb_live) {
# Line 1170  static void audio_run_out (void) Line 1228  static void audio_run_out (void)
1228          }          }
1229    
1230  #ifdef DEBUG_OUT  #ifdef DEBUG_OUT
1231          dolog ("played = %d total %d\n", played, hw->total_samples_played);          dolog ("played=%d\n", played);
1232  #endif  #endif
1233    
1234          if (played) {          if (played) {
1235              hw->ts_helper += played;              hw->ts_helper += played;
1236          }          }
1237    
1238            cleanup_required = 0;
1239          for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {          for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
         again:  
1240              if (!sw->active && sw->empty) {              if (!sw->active && sw->empty) {
1241                  continue;                  continue;
1242              }              }
# Line 1193  static void audio_run_out (void) Line 1251  static void audio_run_out (void)
1251    
1252              if (!sw->total_hw_samples_mixed) {              if (!sw->total_hw_samples_mixed) {
1253                  sw->empty = 1;                  sw->empty = 1;
1254                    cleanup_required |= !sw->active && !sw->callback.fn;
                 if (!sw->active && !sw->callback.fn) {  
                     SWVoiceOut *temp = sw->entries.le_next;  
   
 #ifdef DEBUG_PLIVE  
                     dolog ("Finishing with old voice\n");  
 #endif  
                     AUD_close_out (sw);  
                     sw = temp;  
                     if (sw) {  
                         goto again;  
                     }  
                     else {  
                         break;  
                     }  
                 }  
1255              }              }
1256    
1257              if (sw->active) {              if (sw->active) {
# Line 1218  static void audio_run_out (void) Line 1261  static void audio_run_out (void)
1261                  }                  }
1262              }              }
1263          }          }
1264    
1265            if (cleanup_required) {
1266            restart:
1267                for (sw = hw->sw_head.lh_first; sw; sw = sw->entries.le_next) {
1268                    if (!sw->active && !sw->callback.fn) {
1269    #ifdef DEBUG_PLIVE
1270                        dolog ("Finishing with old voice\n");
1271    #endif
1272                        audio_close_out (s, sw);
1273                        goto restart; /* play it safe */
1274                    }
1275                }
1276            }
1277      }      }
1278  }  }
1279    
1280  static void audio_run_in (void)  static void audio_run_in (AudioState *s)
1281  {  {
1282      HWVoiceIn *hw = NULL;      HWVoiceIn *hw = NULL;
1283    
1284      while ((hw = audio_pcm_hw_find_any_active_enabled_in (hw))) {      while ((hw = audio_pcm_hw_find_any_enabled_in (s, hw))) {
1285          SWVoiceIn *sw;          SWVoiceIn *sw;
1286          int captured, min;          int captured, min;
1287    
# Line 1252  static void audio_run_in (void) Line 1308  static void audio_run_in (void)
1308    
1309  static struct audio_option audio_options[] = {  static struct audio_option audio_options[] = {
1310      /* DAC */      /* DAC */
1311      {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &audio_state.fixed_settings_out,      {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled,
1312       "Use fixed settings for host DAC", NULL, 0},       "Use fixed settings for host DAC", NULL, 0},
1313    
1314      {"DAC_FIXED_FREQ", AUD_OPT_INT, &audio_state.fixed_freq_out,      {"DAC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_out.settings.freq,
1315       "Frequency for fixed host DAC", NULL, 0},       "Frequency for fixed host DAC", NULL, 0},
1316    
1317      {"DAC_FIXED_FMT", AUD_OPT_FMT, &audio_state.fixed_fmt_out,      {"DAC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_out.settings.fmt,
1318       "Format for fixed host DAC", NULL, 0},       "Format for fixed host DAC", NULL, 0},
1319    
1320      {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &audio_state.fixed_channels_out,      {"DAC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_out.settings.nchannels,
1321       "Number of channels for fixed DAC (1 - mono, 2 - stereo)", NULL, 0},       "Number of channels for fixed DAC (1 - mono, 2 - stereo)", NULL, 0},
1322    
1323      {"DAC_VOICES", AUD_OPT_INT, &audio_state.nb_hw_voices_out,      {"DAC_VOICES", AUD_OPT_INT, &conf.fixed_out.nb_voices,
1324       "Number of voices for DAC", NULL, 0},       "Number of voices for DAC", NULL, 0},
1325    
1326      /* ADC */      /* ADC */
1327      {"ADC_FIXED_SETTINGS", AUD_OPT_BOOL, &audio_state.fixed_settings_out,      {"ADC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_in.enabled,
1328       "Use fixed settings for host ADC", NULL, 0},       "Use fixed settings for host ADC", NULL, 0},
1329    
1330      {"ADC_FIXED_FREQ", AUD_OPT_INT, &audio_state.fixed_freq_out,      {"ADC_FIXED_FREQ", AUD_OPT_INT, &conf.fixed_in.settings.freq,
1331       "Frequency for fixed ADC", NULL, 0},       "Frequency for fixed host ADC", NULL, 0},
1332    
1333      {"ADC_FIXED_FMT", AUD_OPT_FMT, &audio_state.fixed_fmt_out,      {"ADC_FIXED_FMT", AUD_OPT_FMT, &conf.fixed_in.settings.fmt,
1334       "Format for fixed ADC", NULL, 0},       "Format for fixed host ADC", NULL, 0},
1335    
1336      {"ADC_FIXED_CHANNELS", AUD_OPT_INT, &audio_state.fixed_channels_in,      {"ADC_FIXED_CHANNELS", AUD_OPT_INT, &conf.fixed_in.settings.nchannels,
1337       "Number of channels for fixed ADC (1 - mono, 2 - stereo)", NULL, 0},       "Number of channels for fixed ADC (1 - mono, 2 - stereo)", NULL, 0},
1338    
1339      {"ADC_VOICES", AUD_OPT_INT, &audio_state.nb_hw_voices_out,      {"ADC_VOICES", AUD_OPT_INT, &conf.fixed_in.nb_voices,
1340       "Number of voices for ADC", NULL, 0},       "Number of voices for ADC", NULL, 0},
1341    
1342      /* Misc */      /* Misc */
1343      {"TIMER_PERIOD", AUD_OPT_INT, &audio_state.period.usec,      {"TIMER_PERIOD", AUD_OPT_INT, &conf.period.hz,
1344       "Timer period in microseconds (0 - try lowest possible)", NULL, 0},       "Timer period in HZ (0 - use lowest possible)", NULL, 0},
1345    
1346      {"PLIVE", AUD_OPT_BOOL, &audio_state.plive,      {"PLIVE", AUD_OPT_BOOL, &conf.plive,
1347       "(undocumented)", NULL, 0},       "(undocumented)", NULL, 0},
1348    
1349      {NULL, 0, NULL, NULL, NULL, 0}      {NULL, 0, NULL, NULL, NULL, 0}
# Line 1378  void audio_timer (void *opaque) Line 1434  void audio_timer (void *opaque)
1434  {  {
1435      AudioState *s = opaque;      AudioState *s = opaque;
1436    
1437      audio_run_out ();      audio_run_out (s);
1438      audio_run_in ();      audio_run_in (s);
1439    
1440      qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + s->period.ticks);      qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
1441  }  }
1442    
1443  static int audio_driver_init (struct audio_driver *drv)  static int audio_driver_init (AudioState *s, struct audio_driver *drv)
1444  {  {
1445      if (drv->options) {      if (drv->options) {
1446          audio_process_options (drv->name, drv->options);          audio_process_options (drv->name, drv->options);
1447      }      }
1448      audio_state.opaque = drv->init ();      s->drv_opaque = drv->init ();
   
     if (audio_state.opaque) {  
         int i;  
         HWVoiceOut *hwo;  
         HWVoiceIn *hwi;  
1449    
1450          if (audio_state.nb_hw_voices_out > drv->max_voices_out) {      if (s->drv_opaque) {
1451            if (s->nb_hw_voices_out > drv->max_voices_out) {
1452              if (!drv->max_voices_out) {              if (!drv->max_voices_out) {
1453                  dolog ("`%s' does not support DAC\n", drv->name);                  dolog ("`%s' does not support DAC\n", drv->name);
1454              }              }
# Line 1405  static int audio_driver_init (struct aud Line 1457  static int audio_driver_init (struct aud
1457                      "`%s' does not support %d multiple DAC voicess\n"                      "`%s' does not support %d multiple DAC voicess\n"
1458                      "Resetting to %d\n",                      "Resetting to %d\n",
1459                      drv->name,                      drv->name,
1460                      audio_state.nb_hw_voices_out,                      s->nb_hw_voices_out,
1461                      drv->max_voices_out                      drv->max_voices_out
1462                      );                      );
1463              }              }
1464              audio_state.nb_hw_voices_out = drv->max_voices_out;              s->nb_hw_voices_out = drv->max_voices_out;
1465          }          }
1466    
         LIST_INIT (&hw_head_out);  
         hwo = qemu_mallocz (audio_state.nb_hw_voices_out * drv->voice_size_out);  
         if (!hwo) {  
             dolog (  
                 "Not enough memory for %d `%s' DAC voices (each %d bytes)\n",  
                 audio_state.nb_hw_voices_out,  
                 drv->name,  
                 drv->voice_size_out  
                 );  
             drv->fini (audio_state.opaque);  
             return -1;  
         }  
   
         for (i = 0; i < audio_state.nb_hw_voices_out; ++i) {  
             LIST_INSERT_HEAD (&hw_head_out, hwo, entries);  
             hwo = advance (hwo, drv->voice_size_out);  
         }  
1467    
1468          if (!drv->voice_size_in && drv->max_voices_in) {          if (!drv->voice_size_in && drv->max_voices_in) {
1469              ldebug ("warning: No ADC voice size defined for `%s'\n",              ldebug ("warning: No ADC voice size defined for `%s'\n",
# Line 1442  static int audio_driver_init (struct aud Line 1477  static int audio_driver_init (struct aud
1477          }          }
1478    
1479          if (drv->voice_size_in && !drv->max_voices_in) {          if (drv->voice_size_in && !drv->max_voices_in) {
1480              ldebug ("warning: ADC voice size is %d for ADC less driver `%s'\n",              ldebug ("warning: `%s' ADC voice size %d, zero voices \n",
1481                      drv->voice_size_out, drv->name);                      drv->name, drv->voice_size_out);
1482          }          }
1483    
1484          if (drv->voice_size_out && !drv->max_voices_out) {          if (drv->voice_size_out && !drv->max_voices_out) {
1485              ldebug ("warning: DAC voice size is %d for DAC less driver `%s'\n",              ldebug ("warning: `%s' DAC voice size %d, zero voices \n",
1486                      drv->voice_size_in, drv->name);                      drv->name, drv->voice_size_in);
1487          }          }
1488    
1489          if (audio_state.nb_hw_voices_in > drv->max_voices_in) {          if (s->nb_hw_voices_in > drv->max_voices_in) {
1490              if (!drv->max_voices_in) {              if (!drv->max_voices_in) {
1491                  ldebug ("`%s' does not support ADC\n", drv->name);                  ldebug ("`%s' does not support ADC\n", drv->name);
1492              }              }
# Line 1460  static int audio_driver_init (struct aud Line 1495  static int audio_driver_init (struct aud
1495                      "`%s' does not support %d multiple ADC voices\n"                      "`%s' does not support %d multiple ADC voices\n"
1496                      "Resetting to %d\n",                      "Resetting to %d\n",
1497                      drv->name,                      drv->name,
1498                      audio_state.nb_hw_voices_in,                      s->nb_hw_voices_in,
1499                      drv->max_voices_in                      drv->max_voices_in
1500                      );                      );
1501              }              }
1502              audio_state.nb_hw_voices_in = drv->max_voices_in;              s->nb_hw_voices_in = drv->max_voices_in;
         }  
   
         LIST_INIT (&hw_head_in);  
         hwi = qemu_mallocz (audio_state.nb_hw_voices_in * drv->voice_size_in);  
         if (!hwi) {  
             dolog (  
                 "Not enough memory for %d `%s' ADC voices (each %d bytes)\n",  
                 audio_state.nb_hw_voices_in,  
                 drv->name,  
                 drv->voice_size_in  
                 );  
             qemu_free (hwo);  
             drv->fini (audio_state.opaque);  
             return -1;  
         }  
   
         for (i = 0; i < audio_state.nb_hw_voices_in; ++i) {  
             LIST_INSERT_HEAD (&hw_head_in, hwi, entries);  
             hwi = advance (hwi, drv->voice_size_in);  
1503          }          }
1504    
1505          audio_state.drv = drv;          LIST_INIT (&s->hw_head_out);
1506            LIST_INIT (&s->hw_head_in);
1507            s->drv = drv;
1508          return 0;          return 0;
1509      }      }
1510      else {      else {
# Line 1497  static int audio_driver_init (struct aud Line 1515  static int audio_driver_init (struct aud
1515    
1516  static void audio_vm_stop_handler (void *opaque, int reason)  static void audio_vm_stop_handler (void *opaque, int reason)
1517  {  {
1518        AudioState *s = opaque;
1519      HWVoiceOut *hwo = NULL;      HWVoiceOut *hwo = NULL;
1520      HWVoiceIn *hwi = NULL;      HWVoiceIn *hwi = NULL;
1521      int op = reason ? VOICE_ENABLE : VOICE_DISABLE;      int op = reason ? VOICE_ENABLE : VOICE_DISABLE;
1522    
1523      (void) opaque;      while ((hwo = audio_pcm_hw_find_any_out (s, hwo))) {
     while ((hwo = audio_pcm_hw_find_any_out (hwo))) {  
1524          if (!hwo->pcm_ops) {          if (!hwo->pcm_ops) {
1525              continue;              continue;
1526          }          }
# Line 1512  static void audio_vm_stop_handler (void Line 1530  static void audio_vm_stop_handler (void
1530          }          }
1531      }      }
1532    
1533      while ((hwi = audio_pcm_hw_find_any_in (hwi))) {      while ((hwi = audio_pcm_hw_find_any_in (s, hwi))) {
1534          if (!hwi->pcm_ops) {          if (!hwi->pcm_ops) {
1535              continue;              continue;
1536          }          }
# Line 1525  static void audio_vm_stop_handler (void Line 1543  static void audio_vm_stop_handler (void
1543    
1544  static void audio_atexit (void)  static void audio_atexit (void)
1545  {  {
1546        AudioState *s = &glob_audio_state;
1547      HWVoiceOut *hwo = NULL;      HWVoiceOut *hwo = NULL;
1548      HWVoiceIn *hwi = NULL;      HWVoiceIn *hwi = NULL;
1549    
1550      while ((hwo = audio_pcm_hw_find_any_out (hwo))) {      while ((hwo = audio_pcm_hw_find_any_out (s, hwo))) {
1551          if (!hwo->pcm_ops) {          if (!hwo->pcm_ops) {
1552              continue;              continue;
1553          }          }
# Line 1539  static void audio_atexit (void) Line 1558  static void audio_atexit (void)
1558          hwo->pcm_ops->fini_out (hwo);          hwo->pcm_ops->fini_out (hwo);
1559      }      }
1560    
1561      while ((hwi = audio_pcm_hw_find_any_in (hwi))) {      while ((hwi = audio_pcm_hw_find_any_in (s, hwi))) {
1562          if (!hwi->pcm_ops) {          if (!hwi->pcm_ops) {
1563              continue;              continue;
1564          }          }
# Line 1549  static void audio_atexit (void) Line 1568  static void audio_atexit (void)
1568          }          }
1569          hwi->pcm_ops->fini_in (hwi);          hwi->pcm_ops->fini_in (hwi);
1570      }      }
1571      audio_state.drv->fini (audio_state.opaque);  
1572        if (s->drv) {
1573            s->drv->fini (s->drv_opaque);
1574        }
1575  }  }
1576    
1577  static void audio_save (QEMUFile *f, void *opaque)  static void audio_save (QEMUFile *f, void *opaque)
# Line 1570  static int audio_load (QEMUFile *f, void Line 1592  static int audio_load (QEMUFile *f, void
1592      return 0;      return 0;
1593  }  }
1594    
1595  void AUD_init (void)  void AUD_register_card (AudioState *s, const char *name, QEMUSoundCard *card)
1596    {
1597        card->audio = s;
1598        card->name = qemu_strdup (name);
1599        memset (&card->entries, 0, sizeof (card->entries));
1600        LIST_INSERT_HEAD (&s->card_head, card, entries);
1601    }
1602    
1603    void AUD_remove_card (QEMUSoundCard *card)
1604    {
1605        LIST_REMOVE (card, entries);
1606        card->audio = NULL;
1607        qemu_free (card->name);
1608    }
1609    
1610    AudioState *AUD_init (void)
1611  {  {
1612      size_t i;      size_t i;
1613      int done = 0;      int done = 0;
1614      const char *drvname;      const char *drvname;
1615      AudioState *s = &audio_state;      AudioState *s = &glob_audio_state;
1616    
1617      audio_process_options ("AUDIO", audio_options);      audio_process_options ("AUDIO", audio_options);
1618    
1619        s->nb_hw_voices_out = conf.fixed_out.nb_voices;
1620        s->nb_hw_voices_in = conf.fixed_in.nb_voices;
1621    
1622      if (s->nb_hw_voices_out <= 0) {      if (s->nb_hw_voices_out <= 0) {
1623          dolog ("Bogus number of DAC voices %d\n",          dolog ("Bogus number of DAC voices %d\n",
1624                 s->nb_hw_voices_out);                 s->nb_hw_voices_out);
# Line 1598  void AUD_init (void) Line 1638  void AUD_init (void)
1638    
1639      s->ts = qemu_new_timer (vm_clock, audio_timer, s);      s->ts = qemu_new_timer (vm_clock, audio_timer, s);
1640      if (!s->ts) {      if (!s->ts) {
1641          dolog ("Can not create audio timer\n");          dolog ("Could not create audio timer\n");
1642          return;          return NULL;
1643      }      }
1644    
1645      if (drvname) {      if (drvname) {
# Line 1607  void AUD_init (void) Line 1647  void AUD_init (void)
1647    
1648          for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {          for (i = 0; i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
1649              if (!strcmp (drvname, drvtab[i]->name)) {              if (!strcmp (drvname, drvtab[i]->name)) {
1650                  done = !audio_driver_init (drvtab[i]);                  done = !audio_driver_init (s, drvtab[i]);
1651                  found = 1;                  found = 1;
1652                  break;                  break;
1653              }              }
# Line 1619  void AUD_init (void) Line 1659  void AUD_init (void)
1659          }          }
1660      }      }
1661    
     qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);  
     atexit (audio_atexit);  
   
1662      if (!done) {      if (!done) {
1663          for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {          for (i = 0; !done && i < sizeof (drvtab) / sizeof (drvtab[0]); i++) {
1664              if (drvtab[i]->can_be_default) {              if (drvtab[i]->can_be_default) {
1665                  done = !audio_driver_init (drvtab[i]);                  done = !audio_driver_init (s, drvtab[i]);
1666              }              }
1667          }          }
1668      }      }
1669    
     register_savevm ("audio", 0, 1, audio_save, audio_load, NULL);  
1670      if (!done) {      if (!done) {
1671          if (audio_driver_init (&no_audio_driver)) {          done = !audio_driver_init (s, &no_audio_driver);
1672              dolog ("Can not initialize audio subsystem\n");          if (!done) {
1673                dolog ("Could not initialize audio subsystem\n");
1674          }          }
1675          else {          else {
1676              dolog ("warning: using timer based audio emulation\n");              dolog ("warning: Using timer based audio emulation\n");
1677          }          }
1678      }      }
1679    
1680      if (s->period.usec <= 0) {      if (done) {
1681          if (s->period.usec < 0) {          if (conf.period.hz <= 0) {
1682              dolog ("warning: timer period is negative - %d treating as zero\n",              if (conf.period.hz < 0) {
1683                     s->period.usec);                  dolog ("warning: Timer period is negative - %d "
1684                           "treating as zero\n",
1685                           conf.period.hz);
1686                }
1687                conf.period.ticks = 1;
1688            }
1689            else {
1690                conf.period.ticks = ticks_per_sec / conf.period.hz;
1691          }          }
1692          s->period.ticks = 1;  
1693            qemu_add_vm_stop_handler (audio_vm_stop_handler, NULL);
1694      }      }
1695      else {      else {
1696          s->period.ticks = (ticks_per_sec * s->period.usec) / 1000000;          qemu_del_timer (s->ts);
1697            return NULL;
1698      }      }
1699    
1700      qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + s->period.ticks);      LIST_INIT (&s->card_head);
1701        register_savevm ("audio", 0, 1, audio_save, audio_load, s);
1702        atexit (audio_atexit);
1703        qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
1704        return s;
1705  }  }

Legend:
Removed from v.1.6  
changed lines
  Added in v.1.7

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