Changeset d988ef2 in mainline


Ignore:
Timestamp:
2013-04-05T12:02:45Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f1438e5
Parents:
4b33db8e
Message:

hound: audio pipe class

This will be used by both streams and connections

Location:
uspace/srv/audio/hound
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/audio/hound/audio_data.c

    r4b33db8e rd988ef2  
    3434 */
    3535
     36#include <macros.h>
    3637#include <malloc.h>
    3738#include "audio_data.h"
    3839
    39 static void ref_inc(audio_data_t *adata)
     40audio_data_t *audio_data_create(const void *data, size_t size,
     41    pcm_format_t format)
     42{
     43        audio_data_t *adata = malloc(sizeof(audio_data_t));
     44        if (adata) {
     45                adata->data = data;
     46                adata->size = size;
     47                adata->format = format;
     48                atomic_set(&adata->refcount, 1);
     49        }
     50        return adata;
     51}
     52
     53void audio_data_addref(audio_data_t *adata)
    4054{
    4155        assert(adata);
     
    4458}
    4559
    46 static void ref_dec(audio_data_t *adata)
     60void audio_data_unref(audio_data_t *adata)
    4761{
    4862        assert(adata);
     
    5569}
    5670
    57 audio_data_t *audio_data_create(const void *data, size_t size,
    58     pcm_format_t format)
    59 {
    60         audio_data_t *adata = malloc(sizeof(audio_data_t));
    61         if (adata) {
    62                 adata->data = data;
    63                 adata->size = size;
    64                 adata->format = format;
    65                 atomic_set(&adata->refcount, 1);
    66         }
    67         return adata;
    68 }
    69 
    70 void audio_data_unref(audio_data_t *adata)
    71 {
    72         ref_dec(adata);
    73 }
    74 
    7571audio_data_link_t *audio_data_link_create(audio_data_t *adata)
    7672{
     
    7874        audio_data_link_t *link = malloc(sizeof(audio_data_link_t));
    7975        if (link) {
    80                 ref_inc(adata);
     76                audio_data_addref(adata);
    8177                link->adata = adata;
    8278                link->position = 0;
     
    10399        assert(link);
    104100        assert(!link_in_use(&link->link));
    105         ref_dec(link->adata);
     101        audio_data_unref(link->adata);
    106102        free(link);
    107103}
     
    111107        assert(alink);
    112108        assert(alink->adata);
    113         return pcm_format_size_to_frames(alink->adata->size - alink->position,
     109        return pcm_format_size_to_frames(audio_data_link_remain_size(alink),
    114110            &alink->adata->format);
     111}
     112
     113/* Audio Pipe */
     114
     115
     116void audio_pipe_init(audio_pipe_t *pipe)
     117{
     118        assert(pipe);
     119        list_initialize(&pipe->list);
     120        fibril_mutex_initialize(&pipe->guard);
     121        pipe->frames = 0;
     122        pipe->bytes = 0;
     123}
     124
     125
     126
     127void audio_pipe_fini(audio_pipe_t *pipe)
     128{
     129        assert(pipe);
     130        while (!list_empty(&pipe->list)) {
     131                audio_data_t *adata = audio_pipe_pop(pipe);
     132                audio_data_unref(adata);
     133        }
     134}
     135
     136int audio_pipe_push(audio_pipe_t *pipe, audio_data_t *data)
     137{
     138        assert(pipe);
     139        assert(data);
     140        audio_data_link_t *alink = audio_data_link_create(data);
     141        if (!alink)
     142                return ENOMEM;
     143
     144        fibril_mutex_lock(&pipe->guard);
     145        list_append(&alink->link, &pipe->list);
     146        pipe->bytes += audio_data_link_remain_size(alink);
     147        pipe->frames += audio_data_link_available_frames(alink);
     148        fibril_mutex_unlock(&pipe->guard);
     149        return EOK;
     150}
     151
     152audio_data_t *audio_pipe_pop(audio_pipe_t *pipe)
     153{
     154        assert(pipe);
     155        fibril_mutex_lock(&pipe->guard);
     156        audio_data_t *adata = NULL;
     157        link_t *l = list_first(&pipe->list);
     158        if (l) {
     159                audio_data_link_t *alink = audio_data_link_list_instance(l);
     160                list_remove(&alink->link);
     161                adata = alink->adata;
     162                audio_data_addref(adata);
     163                audio_data_link_destroy(alink);
     164        }
     165        fibril_mutex_unlock(&pipe->guard);
     166        return adata;
     167}
     168
     169ssize_t audio_pipe_mix_data(audio_pipe_t *pipe, void *data,
     170    size_t size, const pcm_format_t *f)
     171{
     172        assert(pipe);
     173        const size_t dst_frame_size = pcm_format_frame_size(f);
     174        size_t needed_frames = size / dst_frame_size;
     175        size_t copied_size = 0;
     176        fibril_mutex_lock(&pipe->guard);
     177        while (needed_frames > 0 && !list_empty(&pipe->list)) {
     178                /* Get first audio chunk */
     179                link_t *l = list_first(&pipe->list);
     180                audio_data_link_t *alink = audio_data_link_list_instance(l);
     181
     182                /* Get audio chunk metadata */
     183                const size_t src_frame_size =
     184                    pcm_format_frame_size(&alink->adata->format);
     185                const size_t available_frames =
     186                    audio_data_link_available_frames(alink);
     187                const size_t copy_frames = min(available_frames, needed_frames);
     188                const size_t copy_size = copy_frames * dst_frame_size;
     189
     190                /* Copy audio data */
     191                pcm_format_convert_and_mix(data, copy_size,
     192                    audio_data_link_start(alink),
     193                    audio_data_link_remain_size(alink),
     194                    &alink->adata->format, f);
     195
     196                /* Update values */
     197                copied_size += copy_size;
     198                needed_frames -= copy_frames;
     199                data += copy_size;
     200                alink->position += (copy_frames * src_frame_size);
     201                if (audio_data_link_remain_size(alink) == 0) {
     202                        list_remove(&alink->link);
     203                        audio_data_link_destroy(alink);
     204                } else {
     205                        assert(needed_frames == 0);
     206                }
     207        }
     208        fibril_mutex_unlock(&pipe->guard);
     209        return copied_size;
    115210}
    116211
  • uspace/srv/audio/hound/audio_data.h

    r4b33db8e rd988ef2  
    3737#define AUDIO_DATA_H_
    3838
    39 #include <pcm/format.h>
    4039#include <adt/list.h>
    4140#include <atomic.h>
     41#include <errno.h>
     42#include <fibril_synch.h>
     43#include <pcm/format.h>
    4244
    4345typedef struct {
     
    5456} audio_data_link_t;
    5557
     58typedef struct {
     59        list_t list;
     60        size_t bytes;
     61        size_t frames;
     62        fibril_mutex_t guard;
     63} audio_pipe_t;
     64
    5665static inline audio_data_link_t * audio_data_link_list_instance(link_t *l)
    5766{
     
    6170audio_data_t * audio_data_create(const void *data, size_t size,
    6271    pcm_format_t format);
     72void audio_data_addref(audio_data_t *adata);
    6373void audio_data_unref(audio_data_t *adata);
    6474
     
    8393        return alink->adata->size - alink->position;
    8494}
     95
     96void audio_pipe_init(audio_pipe_t *pipe);
     97void audio_pipe_fini(audio_pipe_t *pipe);
     98
     99int audio_pipe_push(audio_pipe_t *pipe, audio_data_t *data);
     100audio_data_t *audio_pipe_pop(audio_pipe_t *pipe);
     101
     102ssize_t audio_pipe_mix_data(audio_pipe_t *pipe, void *buffer, size_t size,
     103    const pcm_format_t *f);
     104
     105static inline size_t audio_pipe_bytes(audio_pipe_t *pipe)
     106{
     107        assert(pipe);
     108        return pipe->bytes;
     109}
     110
     111static inline size_t audio_pipe_frames(audio_pipe_t *pipe)
     112{
     113        assert(pipe);
     114        return pipe->frames;
     115}
     116
     117static inline int audio_pipe_push_data(audio_pipe_t *pipe,
     118    const void *data, size_t size, pcm_format_t f)
     119{
     120        audio_data_t *adata = audio_data_create(data, size, f);
     121        if (adata) {
     122                const int ret = audio_pipe_push(pipe, adata);
     123                audio_data_unref(adata);
     124                return ret;
     125        }
     126        return ENOMEM;
     127}
     128
     129
    85130#endif
    86131
Note: See TracChangeset for help on using the changeset viewer.