Changeset 3e6a975a in mainline for uspace/app/wavplay/dplay.c


Ignore:
Timestamp:
2013-03-16T14:18:26Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1bd99785
Parents:
7ed6ee2
Message:

dplay: Use advantages of non-interrupt approach, play as much as possible.

cleanup
rename 'position' ⇒ 'write_ptr'

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/wavplay/dplay.c

    r7ed6ee2 r3e6a975a  
    5858                void *base;
    5959                size_t size;
    60                 void* position;
     60                void* write_ptr;
    6161        } buffer;
    6262        pcm_format_t f;
     
    7474        pb->buffer.base = NULL;
    7575        pb->buffer.size = 0;
    76         pb->buffer.position = NULL;
     76        pb->buffer.write_ptr = NULL;
    7777        pb->playing = false;
    7878        pb->source = NULL;
     
    111111
    112112                }
    113                 const size_t bytes = fread(pb->buffer.position, sizeof(uint8_t),
    114                    fragment_size, pb->source);
     113                const size_t bytes = fread(pb->buffer.write_ptr,
     114                   sizeof(uint8_t), fragment_size, pb->source);
    115115                printf("Copied from position %p size %zu/%zu\n",
    116                     pb->buffer.position, bytes, fragment_size);
     116                    pb->buffer.write_ptr, bytes, fragment_size);
    117117                if (bytes == 0) {
    118118                        audio_pcm_last_playback_fragment(pb->device);
    119119                }
    120                 bzero(pb->buffer.position + bytes, fragment_size - bytes);
    121                 pb->buffer.position += fragment_size;
    122 
    123                 if (pb->buffer.position >= (pb->buffer.base + pb->buffer.size))
    124                         pb->buffer.position -= pb->buffer.size;
     120                /* any constant is silence */
     121                bzero(pb->buffer.write_ptr + bytes, fragment_size - bytes);
     122                pb->buffer.write_ptr += fragment_size;
     123
     124                if (pb->buffer.write_ptr >= (pb->buffer.base + pb->buffer.size))
     125                        pb->buffer.write_ptr -= pb->buffer.size;
    125126        }
    126127}
     
    146147        printf("Initial: Copied from position %p size %zu/%zu\n",
    147148            pb->buffer.base, bytes, fragment_size);
    148         pb->buffer.position = pb->buffer.base + fragment_size;
     149        pb->buffer.write_ptr = pb->buffer.base + fragment_size;
    149150        fibril_mutex_lock(&pb->mutex);
    150         const unsigned frames = pcm_format_size_to_frames(fragment_size, &pb->f);
     151        const unsigned frames =
     152            pcm_format_size_to_frames(fragment_size, &pb->f);
    151153        ret = audio_pcm_start_playback_fragment(pb->device, frames,
    152154            pb->f.channels, pb->f.sampling_rate, pb->f.sample_format);
     
    166168}
    167169
     170static size_t buffer_occupied(const playback_t *pb, size_t pos)
     171{
     172        assert(pb);
     173        void *read_ptr = pb->buffer.base + pos;
     174        if (read_ptr > pb->buffer.write_ptr)
     175                return pb->buffer.write_ptr + pb->buffer.size - read_ptr;
     176        return pb->buffer.write_ptr - read_ptr;
     177
     178}
     179
     180static size_t buffer_avail(const playback_t *pb, size_t pos)
     181{
     182        assert(pb);
     183        void *read_ptr = pb->buffer.base + pos;
     184        if (read_ptr <= pb->buffer.write_ptr)
     185                return read_ptr + pb->buffer.size - pb->buffer.write_ptr - 1;
     186        return (read_ptr - pb->buffer.write_ptr) - 1;
     187}
     188
     189static size_t buffer_remain(const playback_t *pb)
     190{
     191        assert(pb);
     192        return (pb->buffer.base + pb->buffer.size) - pb->buffer.write_ptr;
     193}
     194
     195static void buffer_advance(playback_t *pb, size_t bytes)
     196{
     197        assert(pb);
     198        pb->buffer.write_ptr += bytes;
     199        while (pb->buffer.write_ptr >= (pb->buffer.base + pb->buffer.size))
     200                pb->buffer.write_ptr -= pb->buffer.size;
     201}
     202
     203
    168204static void play(playback_t *pb)
    169205{
    170206        assert(pb);
    171207        assert(pb->device);
    172         pb->buffer.position = pb->buffer.base;
     208        pb->buffer.write_ptr = pb->buffer.base;
    173209        printf("Playing: %dHz, %s, %d channel(s).\n", pb->f.sampling_rate,
    174210            pcm_sample_format_str(pb->f.sample_format), pb->f.channels);
    175         static useconds_t work_time = 8000; /* 8 ms */
    176         size_t bytes = fread(pb->buffer.position, sizeof(uint8_t),
    177                     pb->buffer.size, pb->source);
    178         if (bytes == 0)
    179                 return;
    180         audio_pcm_start_playback(pb->device,
    181             pb->f.channels, pb->f.sampling_rate, pb->f.sample_format);
     211        useconds_t work_time = 50000; /* 10 ms */
     212        bool started = false;
     213        size_t pos = 0;
    182214        do {
    183                 size_t pos = 0;
    184                 audio_pcm_get_buffer_pos(pb->device, &pos);
    185                 size_t to_play = bytes - pos;
    186                 useconds_t usecs = (bytes > pos) ?
    187                     pcm_format_size_to_usec(to_play, &pb->f) : 0;
    188 
    189                 pb->buffer.position += bytes;
    190 
    191                 printf("%u usecs to play %zu bytes from pos %zu.\n",
    192                     usecs, to_play, pos);
    193                 if (usecs > work_time) {
    194                         async_usleep(usecs - work_time);
    195                         audio_pcm_get_buffer_pos(pb->device, &pos);
    196 //                      printf("Woke up at position %zu/%zu.\n",
    197 //                          pos, pb->buffer.size);
    198                 }
    199 
    200                 /* Remove any overflow */
    201                 while (pb->buffer.position >= pb->buffer.base + pb->buffer.size)
    202                         pb->buffer.position -= pb->buffer.size;
    203 
    204                 if (bytes < pb->buffer.size) {
    205                         const size_t remain = pb->buffer.size -
    206                             (pb->buffer.position - pb->buffer.base);
    207                         /* This was the last part,
    208                          * zero 200 bytes or until the end of buffer. */
    209                         bzero(pb->buffer.position, min(1024, remain));
    210                         if ((pb->buffer.base + pos) > pb->buffer.position) {
    211                                 printf("Overflow: %zu vs. %zu!\n",
    212                                     pos, pb->buffer.position - pb->buffer.base);
    213                         } else {
    214                                 udelay(pcm_format_size_to_usec(
    215                                     pb->buffer.position - pb->buffer.base - pos,
    216                                     &pb->f));
    217                                 audio_pcm_get_buffer_pos(pb->device, &pos);
     215                size_t available = buffer_avail(pb, pos);
     216                /* Writing might need wrap around the end */
     217                size_t bytes = fread(pb->buffer.write_ptr, sizeof(uint8_t),
     218                    min(available, buffer_remain(pb)), pb->source);
     219                buffer_advance(pb, bytes);
     220                printf("POS %zu: %zu bytes free in buffer, read %zu, wp %zu\n",
     221                    pos, available, bytes, pb->buffer.write_ptr - pb->buffer.base);
     222                available -= bytes;
     223                if (available) {
     224                        bytes = fread(pb->buffer.write_ptr,
     225                            sizeof(uint8_t), min(available, buffer_remain(pb)),
     226                            pb->source);
     227                        buffer_advance(pb, bytes);
     228                        printf("POS %zu: %zu bytes still free in buffer, read %zu, wp %zu\n",
     229                            pos, available, bytes, pb->buffer.write_ptr - pb->buffer.base);
     230                        available -= bytes;
     231                }
     232
     233                if (!started) {
     234                        const int ret = audio_pcm_start_playback(pb->device,
     235                            pb->f.channels, pb->f.sampling_rate,
     236                            pb->f.sample_format);
     237                        if (ret != EOK) {
     238                                printf("Failed to start playback\n");
     239                                return;
    218240                        }
    219                         printf("Stopped at %zu(%zu)/%zu\n",
    220                             pos, pb->buffer.position - pb->buffer.base,
    221                             pb->buffer.size);
     241                        started = true;
     242                }
     243                const size_t to_play = buffer_occupied(pb, pos);
     244                const useconds_t usecs =
     245                    pcm_format_size_to_usec(to_play, &pb->f);
     246
     247                const useconds_t real_delay = (usecs > work_time)
     248                    ? usecs - work_time : 0;
     249                printf("POS %zu: %u usecs (%u) to play %zu bytes.\n",
     250                    pos, usecs, real_delay, to_play);
     251                if (real_delay)
     252                        async_usleep(real_delay);
     253                const int ret = audio_pcm_get_buffer_pos(pb->device, &pos);
     254                if (ret != EOK) {
     255                        printf("Failed to update position indicator\n");
     256                }
     257                if (available)
    222258                        break;
    223                 }
    224                 /* copy first half */
    225                 bytes = fread(pb->buffer.position, sizeof(uint8_t),
    226                     pb->buffer.size / 2, pb->source);
    227                 if (bytes == 0)
    228                         break;
    229                 audio_pcm_get_buffer_pos(pb->device, &pos);
    230                 printf("Half buffer copied at pos %zu ", pos);
    231                 /* Wait until the rest of the buffer is ready */
    232                 udelay(pcm_format_size_to_usec(pb->buffer.size - pos, &pb->f));
    233                 /* copy the other part of the buffer */
    234                 if (bytes ==  (pb->buffer.size / 2)) {
    235                         bytes += fread(pb->buffer.position + bytes,
    236                             sizeof(uint8_t), pb->buffer.size / 2, pb->source);
    237                         audio_pcm_get_buffer_pos(pb->device, &pos);
    238                         printf("the other half copied at pos %zu\n", pos);
    239                 }
     259
    240260        } while (1);
    241261        audio_pcm_stop_playback(pb->device);
     
    277297        }
    278298        printf("Buffer: %p %zu.\n", pb.buffer.base, pb.buffer.size);
    279         uintptr_t ptr = 0;
    280         as_get_physical_mapping(pb.buffer.base, &ptr);
    281         printf("buffer mapped at %x.\n", ptr);
     299
     300        {
     301                uintptr_t ptr = 0;
     302                as_get_physical_mapping(pb.buffer.base, &ptr);
     303                printf("buffer mapped at %x.\n", ptr);
     304        }
    282305
    283306        pb.source = fopen(file, "rb");
    284307        if (pb.source == NULL) {
    285308                ret = ENOENT;
    286                 printf("Failed to open %s.\n", file);
     309                printf("Failed to open file: %s.\n", file);
    287310                goto cleanup;
    288311        }
     312
    289313        wave_header_t header;
    290314        fread(&header, sizeof(header), 1, pb.source);
     
    294318        if (ret != EOK) {
    295319                printf("Error parsing wav header: %s.\n", error);
    296                 fclose(pb.source);
    297320                goto cleanup;
    298321        }
Note: See TracChangeset for help on using the changeset viewer.