Changeset 017455e in mainline


Ignore:
Timestamp:
2012-08-30T19:36:14Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b5d2e57
Parents:
e1534533
Message:

wavplay: Implement playback without without using events.

Needs HZ constant changed to 1000 to work reasonably.

File:
1 edited

Legend:

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

    re1534533 r017455e  
    4141#include <audio_pcm_iface.h>
    4242#include <fibril_synch.h>
    43 #include <stdio.h>
     43#include <pcm/format.h>
    4444#include <sys/mman.h>
    4545#include <sys/time.h>
     
    6060                void* position;
    6161        } buffer;
     62        pcm_format_t f;
    6263        FILE* source;
    6364        volatile bool playing;
     
    8687        async_answer_0(iid, EOK);
    8788        playback_t *pb = arg;
    88         const size_t buffer_part = pb->buffer.size / BUFFER_PARTS;
     89        const size_t fragment_size = pb->buffer.size / BUFFER_PARTS;
    8990        while (1) {
    9091                ipc_call_t call;
     
    9394                case PCM_EVENT_PLAYBACK_STARTED:
    9495                case PCM_EVENT_FRAMES_PLAYED:
    95                         printf("%u frames\n", IPC_GET_ARG1(call));
     96                        printf("%u frames: ", IPC_GET_ARG1(call));
    9697                        async_answer_0(callid, EOK);
    9798                        break;
     
    111112                }
    112113                const size_t bytes = fread(pb->buffer.position, sizeof(uint8_t),
    113                    buffer_part, pb->source);
     114                   fragment_size, pb->source);
     115                printf("Copied from position %p size %zu/%zu\n",
     116                    pb->buffer.position, bytes, fragment_size);
    114117                if (bytes == 0) {
    115118                        audio_pcm_last_playback_fragment(pb->device);
    116119                }
    117                 bzero(pb->buffer.position + bytes, buffer_part - bytes);
    118                 pb->buffer.position += buffer_part;
     120                bzero(pb->buffer.position + bytes, fragment_size - bytes);
     121                pb->buffer.position += fragment_size;
    119122
    120123                if (pb->buffer.position >= (pb->buffer.base + pb->buffer.size))
    121                         pb->buffer.position = pb->buffer.base;
    122         }
    123 }
    124 
    125 
    126 static void play(playback_t *pb, unsigned channels, unsigned sampling_rate,
    127     pcm_sample_format_t format)
     124                        pb->buffer.position -= pb->buffer.size;
     125        }
     126}
     127
     128static void play_fragment(playback_t *pb)
    128129{
    129130        assert(pb);
    130131        assert(pb->device);
    131         const size_t buffer_part = pb->buffer.size / BUFFER_PARTS;
    132         pb->buffer.position = pb->buffer.base + buffer_part;
     132        const size_t fragment_size = pb->buffer.size / BUFFER_PARTS;
    133133        printf("Registering event callback\n");
    134134        int ret = audio_pcm_register_event_callback(pb->device,
     
    138138                return;
    139139        }
    140         printf("Playing: %dHz, %s, %d channel(s).\n",
    141             sampling_rate, pcm_sample_format_str(format), channels);
     140        printf("Playing: %dHz, %s, %d channel(s).\n", pb->f.sampling_rate,
     141            pcm_sample_format_str(pb->f.sample_format), pb->f.channels);
    142142        const size_t bytes = fread(pb->buffer.base, sizeof(uint8_t),
    143             buffer_part, pb->source);
    144         if (bytes != buffer_part)
    145                 bzero(pb->buffer.base + bytes, buffer_part - bytes);
    146         printf("Buffer data ready.\n");
     143            fragment_size, pb->source);
     144        if (bytes != fragment_size)
     145                bzero(pb->buffer.base + bytes, fragment_size - bytes);
     146        printf("Initial: Copied from position %p size %zu/%zu\n",
     147            pb->buffer.base, bytes, fragment_size);
     148        pb->buffer.position = pb->buffer.base + fragment_size;
    147149        fibril_mutex_lock(&pb->mutex);
    148         const unsigned frames = pb->buffer.size /
    149             (BUFFER_PARTS * channels * pcm_sample_format_size(format));
    150         ret = audio_pcm_start_playback_fragment(pb->device, frames, channels,
    151             sampling_rate, format);
     150        const unsigned frames = pcm_format_size_to_frames(fragment_size, &pb->f);
     151        ret = audio_pcm_start_playback_fragment(pb->device, frames,
     152            pb->f.channels, pb->f.sampling_rate, pb->f.sample_format);
    152153        if (ret != EOK) {
    153154                fibril_mutex_unlock(&pb->mutex);
    154155                printf("Failed to start playback: %s.\n", str_error(ret));
     156                audio_pcm_unregister_event_callback(pb->device);
    155157                return;
    156158        }
     
    164166}
    165167
     168static void play(playback_t *pb)
     169{
     170        assert(pb);
     171        assert(pb->device);
     172        pb->buffer.position = pb->buffer.base;
     173        printf("Playing: %dHz, %s, %d channel(s).\n", pb->f.sampling_rate,
     174            pcm_sample_format_str(pb->f.sample_format), pb->f.channels);
     175        static suseconds_t work_time = 8000; /* 2 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);
     182        do {
     183                size_t pos = 0;
     184                audio_pcm_get_buffer_pos(pb->device, &pos);
     185                useconds_t usecs = pcm_format_size_to_usec(bytes - pos, &pb->f);
     186
     187                pb->buffer.position += bytes;
     188
     189                printf("%u usecs to play %zu bytes from pos %zu.\n",
     190                    usecs, bytes, pos);
     191                async_usleep(usecs - work_time);
     192                audio_pcm_get_buffer_pos(pb->device, &pos);
     193                printf("Woke up at position %zu/%zu.\n", pos, pb->buffer.size);
     194
     195                /* Remove any overflow */
     196                while (pb->buffer.position >= pb->buffer.base + pb->buffer.size)
     197                        pb->buffer.position -= pb->buffer.size;
     198
     199                if (bytes < pb->buffer.size) {
     200                        const size_t remain = pb->buffer.size -
     201                            (pb->buffer.position - pb->buffer.base);
     202                        /* This was the last part,
     203                         * zero 200 bytes or until the end of buffer. */
     204                        bzero(pb->buffer.position, min(200, remain));
     205                        if ((pb->buffer.base + pos) > pb->buffer.position) {
     206                                printf("Overflow: %zu vs. %zu!\n",
     207                                    pos, pb->buffer.position - pb->buffer.base);
     208                        } else {
     209                                udelay(pcm_format_size_to_usec(
     210                                    pb->buffer.position - pb->buffer.base - pos,
     211                                    &pb->f));
     212                                audio_pcm_get_buffer_pos(pb->device, &pos);
     213                        }
     214                        printf("Stopped at %zu(%zu)/%zu\n",
     215                            pos, pb->buffer.position - pb->buffer.base,
     216                            pb->buffer.size);
     217                        break;
     218                }
     219                /* copy first half */
     220                bytes = fread(pb->buffer.position, sizeof(uint8_t),
     221                    pb->buffer.size / 2, pb->source);
     222                if (bytes == 0)
     223                        break;
     224                audio_pcm_get_buffer_pos(pb->device, &pos);
     225                printf("Half buffer copied at pos %zu", pos);
     226                /* Wait until the rest of the buffer is ready */
     227                udelay(pcm_format_size_to_usec(pb->buffer.size - pos, &pb->f));
     228                /* copy the other part of the buffer */
     229                audio_pcm_get_buffer_pos(pb->device, &pos);
     230                printf(" the other half copied at pos %zu\n", pos);
     231                bytes += fread(pb->buffer.position + bytes, sizeof(uint8_t),
     232                            pb->buffer.size / 2, pb->source);
     233        } while (1);
     234        audio_pcm_stop_playback(pb->device);
     235}
     236
    166237int dplay(const char *device, const char *file)
    167238{
     239        int ret = EOK;
    168240        if (str_cmp(device, "default") == 0)
    169241                device = DEFAULT_DEVICE;
     
    174246        }
    175247        printf("Playing on device: %s.\n", device);
     248        if (audio_pcm_query_cap(session, AUDIO_CAP_PLAYBACK) <= 0) {
     249                printf("Device %s does not support playback\n", device);
     250                ret = ENOTSUP;
     251                goto close_session;
     252        }
    176253
    177254        const char* info = NULL;
    178         int ret = audio_pcm_get_info_str(session, &info);
     255        ret = audio_pcm_get_info_str(session, &info);
    179256        if (ret != EOK) {
    180257                printf("Failed to get PCM info.\n");
     
    205282        wave_header_t header;
    206283        fread(&header, sizeof(header), 1, pb.source);
    207         unsigned rate, channels;
    208         pcm_sample_format_t format;
    209284        const char *error;
    210         ret = wav_parse_header(&header, NULL, NULL, &channels, &rate, &format,
    211             &error);
     285        ret = wav_parse_header(&header, NULL, NULL,
     286            &pb.f.channels, &pb.f.sampling_rate, &pb.f.sample_format, &error);
    212287        if (ret != EOK) {
    213288                printf("Error parsing wav header: %s.\n", error);
     
    215290                goto cleanup;
    216291        }
    217 
    218         play(&pb, channels, rate, format);
     292        if (audio_pcm_query_cap(pb.device, AUDIO_CAP_BUFFER_POS) > 0) {
     293                play(&pb);
     294        } else {
     295                if (audio_pcm_query_cap(pb.device, AUDIO_CAP_INTERRUPT) > 0)
     296                        play_fragment(&pb);
     297                else
     298                        printf("Neither playing method is supported");
     299        }
     300
     301cleanup:
    219302        fclose(pb.source);
    220 
    221 cleanup:
    222303        munmap(pb.buffer.base, pb.buffer.size);
    223304        audio_pcm_release_buffer(pb.device);
Note: See TracChangeset for help on using the changeset viewer.