[BACK]Return to dev.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / sndiod

Diff for /src/usr.bin/sndiod/dev.c between version 1.11 and 1.12

version 1.11, 2014/03/05 20:24:16 version 1.12, 2014/03/05 20:31:22
Line 55 
Line 55 
 void dev_mix_badd(struct dev *, struct slot *);  void dev_mix_badd(struct dev *, struct slot *);
 void dev_empty_cycle(struct dev *);  void dev_empty_cycle(struct dev *);
 void dev_mix_adjvol(struct dev *);  void dev_mix_adjvol(struct dev *);
 void dev_mix_cycle(struct dev *);  
 int rec_filt_resamp(struct slot *, void *, void *, int);  int rec_filt_resamp(struct slot *, void *, void *, int);
 int rec_filt_enc(struct slot *, void *, void *, int);  int rec_filt_enc(struct slot *, void *, void *, int);
 void dev_sub_bcopy(struct dev *, struct slot *);  void dev_sub_bcopy(struct dev *, struct slot *);
 void dev_sub_cycle(struct dev *);  void dev_full_cycle(struct dev *);
   
 void dev_onmove(struct dev *, int);  void dev_onmove(struct dev *, int);
 void dev_master(struct dev *, unsigned int);  void dev_master(struct dev *, unsigned int);
Line 93 
Line 92 
 void slot_start(struct slot *);  void slot_start(struct slot *);
 void slot_detach(struct slot *);  void slot_detach(struct slot *);
 void slot_stop(struct slot *);  void slot_stop(struct slot *);
   void slot_skip_update(struct slot *);
 void slot_write(struct slot *);  void slot_write(struct slot *);
 void slot_read(struct slot *);  void slot_read(struct slot *);
 void slot_mix_drop(struct slot *);  int slot_skip(struct slot *);
 void slot_sub_sil(struct slot *);  
   
 struct midiops dev_midiops = {  struct midiops dev_midiops = {
         dev_midi_imsg,          dev_midi_imsg,
Line 541 
Line 540 
                 dev_close(d);                  dev_close(d);
 }  }
   
 void  int
 slot_mix_drop(struct slot *s)  slot_skip(struct slot *s)
 {  {
         while (s->mix.drop > 0 && s->mix.buf.used >= s->round * s->mix.bpf) {          unsigned char *data = (unsigned char *)0xdeadbeef; /* please gcc */
 #ifdef DEBUG          int max, count;
                 if (log_level >= 4) {  
                         slot_log(s);  
                         log_puts(": dropped a play block\n");  
                 }  
 #endif  
                 abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);  
                 s->mix.drop--;  
         }  
 }  
   
 void          max = s->skip;
 slot_sub_sil(struct slot *s)          while (s->skip > 0) {
 {                  if (s->pstate != SLOT_STOP && (s->mode & MODE_RECMASK)) {
         unsigned char *data;                          data = abuf_wgetblk(&s->sub.buf, &count);
         int count;                          if (count < s->round * s->sub.bpf)
                                   break;
         while (s->sub.silence > 0) {                  }
                 data = abuf_wgetblk(&s->sub.buf, &count);                  if (s->mode & MODE_PLAY) {
                 if (count < s->round * s->sub.bpf)                          if (s->mix.buf.used < s->round * s->mix.bpf)
                         break;                                  break;
                   }
 #ifdef DEBUG  #ifdef DEBUG
                 if (log_level >= 4) {                  if (log_level >= 4) {
                         slot_log(s);                          slot_log(s);
                         log_puts(": inserted a rec block of silence\n");                          log_puts(": skipped a cycle\n");
                 }                  }
 #endif  #endif
                 if (s->sub.encbuf)                  if (s->pstate != SLOT_STOP && (s->mode & MODE_RECMASK)) {
                         enc_sil_do(&s->sub.enc, data, s->round);                          if (s->sub.encbuf)
                 else                                  enc_sil_do(&s->sub.enc, data, s->round);
                         memset(data, 0, s->round * s->sub.bpf);                          else
                 abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);                                  memset(data, 0, s->round * s->sub.bpf);
                 s->sub.silence--;                          abuf_wcommit(&s->sub.buf, s->round * s->sub.bpf);
                   }
                   if (s->mode & MODE_PLAY) {
                           abuf_rdiscard(&s->mix.buf, s->round * s->mix.bpf);
                   }
                   s->skip--;
         }          }
           return max - s->skip;
 }  }
   
 /*  /*
Line 716 
Line 713 
         }          }
 }  }
   
 void  
 dev_mix_cycle(struct dev *d)  
 {  
         struct slot *s, **ps;  
         unsigned char *base;  
         int nsamp;  
   
 #ifdef DEBUG  
         if (log_level >= 4) {  
                 dev_log(d);  
                 log_puts(": dev_mix_cycle, poffs = ");  
                 log_puti(d->poffs);  
                 log_puts("\n");  
         }  
 #endif  
         base = (unsigned char *)DEV_PBUF(d);  
         nsamp = d->round * d->pchan;  
         memset(base, 0, nsamp * sizeof(adata_t));  
         ps = &d->slot_list;  
         while ((s = *ps) != NULL) {  
                 if (!(s->mode & MODE_PLAY)) {  
                         ps = &s->next;  
                         continue;  
                 }  
 #ifdef DEBUG  
                 if (log_level >= 4) {  
                         slot_log(s);  
                         log_puts(": mixing, drop = ");  
                         log_puti(s->mix.drop);  
                         log_puts(" cycles\n");  
                 }  
 #endif  
                 slot_mix_drop(s);  
                 if (s->mix.drop < 0) {  
                         s->mix.drop++;  
                         ps = &s->next;  
                         continue;  
                 }  
                 if (s->mix.buf.used < s->round * s->mix.bpf &&  
                     s->pstate == SLOT_STOP) {  
                         /*  
                          * partial blocks are zero-filled by socket  
                          * layer  
                          */  
                         s->pstate = SLOT_INIT;  
                         abuf_done(&s->mix.buf);  
                         if (s->mix.decbuf)  
                                 xfree(s->mix.decbuf);  
                         if (s->mix.resampbuf)  
                                 xfree(s->mix.resampbuf);  
                         s->ops->eof(s->arg);  
                         *ps = s->next;  
                         dev_mix_adjvol(d);  
                         continue;  
                 }  
                 if (s->mix.buf.used < s->round * s->mix.bpf &&  
                     !(s->pstate == SLOT_STOP)) {  
                         if (s->xrun == XRUN_IGNORE) {  
                                 if (s->mode & MODE_RECMASK)  
                                         s->sub.silence--;  
                                 s->delta -= s->round;  
 #ifdef DEBUG  
                                 if (log_level >= 3) {  
                                         slot_log(s);  
                                         log_puts(": underrun, pause cycle\n");  
                                 }  
 #endif  
                                 ps = &s->next;  
                                 continue;  
                         }  
                         if (s->xrun == XRUN_SYNC) {  
                                 s->mix.drop++;  
                                 ps = &s->next;  
                                 continue;  
                         }  
                         if (s->xrun == XRUN_ERROR) {  
                                 s->ops->exit(s->arg);  
                                 *ps = s->next;  
                                 continue;  
                         }  
                 } else {  
                         dev_mix_badd(d, s);  
                         if (s->pstate != SLOT_STOP)  
                                 s->ops->fill(s->arg);  
                 }  
                 ps = &s->next;  
         }  
         if (d->encbuf) {  
                 enc_do(&d->enc, (unsigned char *)DEV_PBUF(d),  
                     d->encbuf, d->round);  
         }  
 }  
   
 int  int
 rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo)  rec_filt_resamp(struct slot *s, void *in, void *res_out, int todo)
 {  {
Line 872 
Line 776 
 }  }
   
 void  void
 dev_sub_cycle(struct dev *d)  dev_full_cycle(struct dev *d)
 {  {
         struct slot *s, **ps;          struct slot *s, **ps;
           unsigned char *base;
           int nsamp;
   
           d->delta -= d->round;
 #ifdef DEBUG  #ifdef DEBUG
         if (log_level >= 4) {          if (log_level >= 4) {
                 dev_log(d);                  dev_log(d);
                 log_puts(": dev_sub_cycle\n");                  log_puts(": dev_full_cycle: clk=");
                   log_puti(d->delta);
                   if (d->mode & MODE_PLAY) {
                           log_puts(", poffs = ");
                           log_puti(d->poffs);
                   }
                   log_puts("\n");
         }          }
 #endif  #endif
           if (d->mode & MODE_PLAY) {
                   base = (unsigned char *)DEV_PBUF(d);
                   nsamp = d->round * d->pchan;
                   memset(base, 0, nsamp * sizeof(adata_t));
           }
         if ((d->mode & MODE_REC) && d->decbuf)          if ((d->mode & MODE_REC) && d->decbuf)
                 dec_do(&d->dec, d->decbuf, (unsigned char *)d->rbuf, d->round);                  dec_do(&d->dec, d->decbuf, (unsigned char *)d->rbuf, d->round);
         ps = &d->slot_list;          ps = &d->slot_list;
         while ((s = *ps) != NULL) {          while ((s = *ps) != NULL) {
                 if (!(s->mode & MODE_RECMASK) || s->pstate == SLOT_STOP) {  #ifdef DEBUG
                   if (log_level >= 4) {
                           slot_log(s);
                           log_puts(": running");
                           log_puts(", skip = ");
                           log_puti(s->skip);
                           log_puts("\n");
                   }
   #endif
                   /*
                    * skip cycles for XRUN_SYNC correction
                    */
                   slot_skip(s);
                   if (s->skip < 0) {
                           s->skip++;
                         ps = &s->next;                          ps = &s->next;
                         continue;                          continue;
                 }                  }
                 slot_sub_sil(s);  
                 if (s->sub.silence < 0) {  #ifdef DEBUG
                         s->sub.silence++;                  if (s->pstate == SLOT_STOP && !(s->mode & MODE_PLAY)) {
                         ps = &s->next;                          slot_log(s);
                           log_puts(": rec-only slots can't be drained\n");
                           panic();
                   }
   #endif
                   /*
                    * check if stopped stream finished draining
                    */
                   if (s->pstate == SLOT_STOP &&
                       s->mix.buf.used < s->round * s->mix.bpf) {
                           /*
                            * partial blocks are zero-filled by socket
                            * layer, so s->mix.buf.used == 0 and we can
                            * destroy the buffer
                            */
                           s->pstate = SLOT_INIT;
                           abuf_done(&s->mix.buf);
                           if (s->mix.decbuf)
                                   xfree(s->mix.decbuf);
                           if (s->mix.resampbuf)
                                   xfree(s->mix.resampbuf);
                           s->ops->eof(s->arg);
                           *ps = s->next;
                           dev_mix_adjvol(d);
                         continue;                          continue;
                 }                  }
                 if (s->sub.buf.len - s->sub.buf.used < s->round * s->sub.bpf) {  
                   /*
                    * check for xruns
                    */
                   if (((s->mode & MODE_PLAY) &&
                           s->mix.buf.used < s->round * s->mix.bpf) ||
                       ((s->mode & MODE_RECMASK) &&
                           s->sub.buf.len - s->sub.buf.used <
                           s->round * s->sub.bpf)) {
   
   #ifdef DEBUG
                           if (log_level >= 3) {
                                   slot_log(s);
                                   log_puts(": xrun, pause cycle\n");
                           }
   #endif
                         if (s->xrun == XRUN_IGNORE) {                          if (s->xrun == XRUN_IGNORE) {
                                 if (s->mode & MODE_PLAY)  
                                         s->mix.drop--;  
                                 s->delta -= s->round;                                  s->delta -= s->round;
                                   ps = &s->next;
                           } else if (s->xrun == XRUN_SYNC) {
                                   s->skip++;
                                   ps = &s->next;
                           } else if (s->xrun == XRUN_ERROR) {
                                   s->ops->exit(s->arg);
                                   *ps = s->next;
                           } else {
 #ifdef DEBUG  #ifdef DEBUG
                                   slot_log(s);
                                   log_puts(": bad xrun mode\n");
                                   panic();
   #endif
                           }
                           continue;
                   }
                   if (s->mode & MODE_PLAY) {
                           dev_mix_badd(d, s);
                           if (s->pstate != SLOT_STOP)
                                   s->ops->fill(s->arg);
                   }
                   if ((s->mode & MODE_RECMASK) && !(s->pstate == SLOT_STOP)) {
                           if (s->sub.prime == 0) {
                                   dev_sub_bcopy(d, s);
                                   s->ops->flush(s->arg);
                           } else {
   #ifdef DEBUG
                                 if (log_level >= 3) {                                  if (log_level >= 3) {
                                         slot_log(s);                                          slot_log(s);
                                         log_puts(": overrun, pause cycle\n");                                          log_puts(": prime = ");
                                           log_puti(s->sub.prime);
                                           log_puts("\n");
                                 }                                  }
 #endif  #endif
                                 ps = &s->next;                                  s->sub.prime--;
                                 continue;  
                         }                          }
                         if (s->xrun == XRUN_SYNC) {  
                                 s->sub.silence++;  
                                 ps = &s->next;  
                                 continue;  
                         }  
                         if (s->xrun == XRUN_ERROR) {  
                                 s->ops->exit(s->arg);  
                                 *ps = s->next;  
                                 continue;  
                         }  
                 } else {  
                         dev_sub_bcopy(d, s);  
                         s->ops->flush(s->arg);  
                 }                  }
                 ps = &s->next;                  ps = &s->next;
         }          }
           if ((d->mode & MODE_PLAY) && d->encbuf) {
                   enc_do(&d->enc, (unsigned char *)DEV_PBUF(d),
                       d->encbuf, d->round);
           }
 }  }
   
 /*  /*
Line 935 
Line 921 
 dev_onmove(struct dev *d, int delta)  dev_onmove(struct dev *d, int delta)
 {  {
         long long pos;          long long pos;
         struct slot *s, *snext;          struct slot *s, *snext;
   
         /*          d->delta += delta;
          * s->ops->onmove() may remove the slot  
          */  
         for (s = d->slot_list; s != NULL; s = snext) {          for (s = d->slot_list; s != NULL; s = snext) {
                   /*
                    * s->ops->onmove() may remove the slot
                    */
                 snext = s->next;                  snext = s->next;
                 pos = (long long)delta * s->round + s->delta_rem;                  pos = (long long)delta * s->round + s->delta_rem;
                 s->delta_rem = pos % d->round;                  s->delta_rem = pos % d->round;
Line 994 
Line 982 
                 d->prime -= d->round;                  d->prime -= d->round;
                 dev_empty_cycle(d);                  dev_empty_cycle(d);
         } else {          } else {
                 if (d->mode & MODE_RECMASK)                  dev_full_cycle(d);
                         dev_sub_cycle(d);  
                 if (d->mode & MODE_PLAY)  
                         dev_mix_cycle(d);  
         }          }
 }  }
   
Line 1332 
Line 1317 
                 } else {                  } else {
                         d->prime = 0;                          d->prime = 0;
                 }                  }
   
                   /* empty cycles don't increment delta */
                   d->delta = 0;
   
                 d->pstate = DEV_RUN;                  d->pstate = DEV_RUN;
                 dev_sio_start(d);                  dev_sio_start(d);
         }          }
Line 1675 
Line 1664 
 {  {
         struct dev *d = s->dev;          struct dev *d = s->dev;
         unsigned int slot_nch, dev_nch;          unsigned int slot_nch, dev_nch;
           long long pos;
         int startpos;          int startpos;
   
         /*          /*
Line 1687 
Line 1677 
          * played and/or recorded           * played and/or recorded
          */           */
         startpos = dev_getpos(d) * (int)s->round / (int)d->round;          startpos = dev_getpos(d) * (int)s->round / (int)d->round;
         s->delta = startpos;  
         s->delta_rem = 0;          /*
            * adjust initial clock
            */
           pos = (long long)d->delta * s->round;
           s->delta = startpos + pos / (int)d->round;
           s->delta_rem = pos % d->round;
   
         s->pstate = SLOT_RUN;          s->pstate = SLOT_RUN;
 #ifdef DEBUG  #ifdef DEBUG
         if (log_level >= 3) {          if (log_level >= 0) {
                 slot_log(s);                  slot_log(s);
                 log_puts(": attached at ");                  log_puts(": attached at ");
                 log_puti(startpos);                  log_puti(startpos);
                   log_puts(", delta = ");
                   log_puti(d->delta);
                 log_puts("\n");                  log_puts("\n");
         }          }
 #endif  #endif
Line 1713 
Line 1711 
 #endif  #endif
         s->next = d->slot_list;          s->next = d->slot_list;
         d->slot_list = s;          d->slot_list = s;
           s->skip = 0;
         if (s->mode & MODE_PLAY) {          if (s->mode & MODE_PLAY) {
                 slot_nch = s->mix.slot_cmax - s->mix.slot_cmin + 1;                  slot_nch = s->mix.slot_cmax - s->mix.slot_cmin + 1;
                 dev_nch = s->mix.dev_cmax - s->mix.dev_cmin + 1;                  dev_nch = s->mix.dev_cmax - s->mix.dev_cmin + 1;
Line 1742 
Line 1741 
                         s->mix.resampbuf =                          s->mix.resampbuf =
                             xmalloc(d->round * slot_nch * sizeof(adata_t));                              xmalloc(d->round * slot_nch * sizeof(adata_t));
                 }                  }
                 s->mix.drop = 0;  
                 s->mix.vol = MIDI_TO_ADATA(s->vol);                  s->mix.vol = MIDI_TO_ADATA(s->vol);
                 dev_mix_adjvol(d);                  dev_mix_adjvol(d);
         }          }
Line 1779 
Line 1777 
                 /*                  /*
                  * N-th recorded block is the N-th played block                   * N-th recorded block is the N-th played block
                  */                   */
                 s->sub.silence = startpos / (int)s->round;                  s->sub.prime = -startpos / (int)s->round;
         }          }
 }  }
   
Line 1958 
Line 1956 
                 s->tstate = MMC_STOP;                  s->tstate = MMC_STOP;
 }  }
   
   void
   slot_skip_update(struct slot *s)
   {
           int skip;
   
           skip = slot_skip(s);
           while (skip > 0) {
   #ifdef DEBUG
                   if (log_level >= 4) {
                           slot_log(s);
                           log_puts(": catching skipped block\n");
                   }
   #endif
                   if (s->mode & MODE_RECMASK)
                           s->ops->flush(s->arg);
                   if (s->mode & MODE_PLAY)
                           s->ops->fill(s->arg);
                   skip--;
           }
   }
   
 /*  /*
  * notify the slot that we just wrote in the play buffer, must be called   * notify the slot that we just wrote in the play buffer, must be called
  * after each write   * after each write
Line 1965 
Line 1984 
 void  void
 slot_write(struct slot *s)  slot_write(struct slot *s)
 {  {
         int drop;  
   
         if (s->pstate == SLOT_START && s->mix.buf.used == s->mix.buf.len) {          if (s->pstate == SLOT_START && s->mix.buf.used == s->mix.buf.len) {
 #ifdef DEBUG  #ifdef DEBUG
                 if (log_level >= 4) {                  if (log_level >= 4) {
Line 1977 
Line 1994 
                 s->pstate = SLOT_READY;                  s->pstate = SLOT_READY;
                 slot_ready(s);                  slot_ready(s);
         }          }
         drop = s->mix.drop;          slot_skip_update(s);
         slot_mix_drop(s);  
         while (drop > s->mix.drop) {  
 #ifdef DEBUG  
                 if (log_level >= 4) {  
                         slot_log(s);  
                         log_puts(": catching play block\n");  
                 }  
 #endif  
                 s->ops->fill(s->arg);  
                 drop--;  
         }  
 }  }
   
 /*  /*
Line 1997 
Line 2003 
 void  void
 slot_read(struct slot *s)  slot_read(struct slot *s)
 {  {
         int sil;          slot_skip_update(s);
   
         sil = s->sub.silence;  
         slot_sub_sil(s);  
         while (sil > s->sub.silence) {  
 #ifdef DEBUG  
                 if (log_level >= 4) {  
                         slot_log(s);  
                         log_puts(": catching rec block\n");  
                 }  
 #endif  
                 s->ops->flush(s->arg);  
                 sil--;  
         }  
 }  }

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12