@@ -321,6 +321,8 @@ typedef struct {
321321 // PCM frame doubly-ended queue
322322 vsnd_buf_queue_node_t buf ;
323323 struct list_head buf_queue_head ;
324+ // PCM frame immediate buffer;
325+ void * immediate ;
324326
325327 // playback control
326328 vsnd_stream_sel_t v ;
@@ -552,7 +554,7 @@ static void virtio_snd_read_pcm_prepare(const virtio_snd_pcm_hdr_t *query,
552554 /* CNFA only accept frame with signed 16-bit data in little-endian. */
553555 props -> audio_host =
554556 CNFAInit (NULL , "semu-virtio-snd" , virtio_snd_cb , rate , 0 , channels , 0 ,
555- period_bytes / VSND_CNFA_FRAME_SZ , NULL , NULL , & props -> v );
557+ cnfa_period_frames , NULL , NULL , & props -> v );
556558 uint32_t sz = props -> pp .buffer_bytes ;
557559 props -> ring .buffer = (void * ) malloc (sizeof (void ) * sz );
558560 props -> ring .prod .head = 0 ;
@@ -567,6 +569,7 @@ static void virtio_snd_read_pcm_prepare(const virtio_snd_pcm_hdr_t *query,
567569 pthread_cond_init (& props -> ring .readable , NULL );
568570 pthread_cond_init (& props -> ring .writable , NULL );
569571 INIT_LIST_HEAD (& props -> buf_queue_head );
572+ props -> immediate = (void * )malloc (sizeof (void ) * cnfa_period_bytes );
570573#if WRITEOUT
571574 outfile = fopen ("out_enque.bin" , "wb" );
572575#endif
@@ -648,6 +651,7 @@ static void virtio_snd_read_pcm_release(const virtio_snd_pcm_hdr_t *query,
648651#endif
649652 /* Tear down the PCM ring buffer. */
650653 free (props -> ring .buffer );
654+ free (props -> immediate );
651655 pthread_mutex_destroy (& props -> ring .lock );
652656 pthread_cond_destroy (& props -> ring .readable );
653657 pthread_cond_destroy (& props -> ring .writable );
@@ -710,26 +714,46 @@ static void __virtio_snd_frame_dequeue(short *out,
710714 "cons_head %" PRIu32 " cons_next %" PRIu32 " prod_tail %" PRIu32
711715 " mask %" PRIu32 " idx %" PRIu32 "\n" ,
712716 cons_head , cons_next , prod_tail , mask , idx );
713- if (idx + n < size ) {
717+ /* if (idx + n < size) {
714718 memcpy(out, props->ring.buffer + idx, n);
715719 } else {
716720 memcpy(out, props->ring.buffer + idx, size - idx);
717721 memcpy(out + (size - idx), props->ring.buffer, n - (size - idx));
718722 fprintf(stderr, "=== start %" PRIu32 " end %" PRIu32 "\n", size - idx,
719723 n - (size - idx));
720- }
724+ }*/
721725 VSND_COMPILER_BARRIER ;
722726
723727 props -> ring .cons .tail = cons_next ;
724728
725- /*uint32_t len = 0;
726- while (!list_empty(&props->buf_queue_head) && len < n) {
729+ uint32_t written_bytes = 0 ;
730+ memset (props -> immediate , 0 , sizeof (void ) * n );
731+ while (!list_empty (& props -> buf_queue_head ) && written_bytes < n ) {
727732 vsnd_buf_queue_node_t * node =
728733 list_first_entry (& props -> buf_queue_head , vsnd_buf_queue_node_t , q );
729- list_del(&node->q);
730- memcpy(out, node->addr, node->len);
731- len += node->len;
732- }*/
734+ uint32_t left = n - written_bytes ;
735+ uint32_t actual = node -> len - node -> pos ;
736+ uint32_t len = left < actual ? left : actual ; /* Naive min implementation */
737+
738+ fprintf (stderr ,
739+ "--- left %" PRIu32 " actual %" PRIu32 " len %" PRIu32 " written %" PRIu32 "\n" ,
740+ left ,
741+ actual ,
742+ len ,
743+ written_bytes );
744+
745+ memcpy (
746+ props -> immediate + written_bytes ,
747+ node -> addr ,
748+ len );
749+
750+ written_bytes += len ;
751+ node -> pos += len ;
752+ if (node -> pos >= node -> len )
753+ list_del (& node -> q );
754+ }
755+ fprintf (stderr , "*** written %" PRIu32 " out n %" PRIu32 "\n" , written_bytes , n );
756+ memcpy (out , props -> immediate , n );
733757
734758 props -> ring .buf_ev_notity -- ;
735759 pthread_cond_signal (& props -> ring .writable );
0 commit comments