source: mainline/uspace/srv/audio/hound/audio_data.c@ d988ef2

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d988ef2 was d988ef2, checked in by Jan Vesely <jano.vesely@…>, 12 years ago

hound: audio pipe class

This will be used by both streams and connections

  • Property mode set to 100644
File size: 5.7 KB
Line 
1/*
2 * Copyright (c) 2013 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup audio
30 * @brief HelenOS sound server
31 * @{
32 */
33/** @file
34 */
35
36#include <macros.h>
37#include <malloc.h>
38#include "audio_data.h"
39
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)
54{
55 assert(adata);
56 assert(atomic_get(&adata->refcount) > 0);
57 atomic_inc(&adata->refcount);
58}
59
60void audio_data_unref(audio_data_t *adata)
61{
62 assert(adata);
63 assert(atomic_get(&adata->refcount) > 0);
64 atomic_count_t refc = atomic_predec(&adata->refcount);
65 if (refc == 0) {
66 free(adata->data);
67 free(adata);
68 }
69}
70
71audio_data_link_t *audio_data_link_create(audio_data_t *adata)
72{
73 assert(adata);
74 audio_data_link_t *link = malloc(sizeof(audio_data_link_t));
75 if (link) {
76 audio_data_addref(adata);
77 link->adata = adata;
78 link->position = 0;
79 }
80 return link;
81}
82
83audio_data_link_t * audio_data_link_create_data(const void *data, size_t size,
84 pcm_format_t format)
85{
86 audio_data_link_t *link = NULL;
87 audio_data_t *adata = audio_data_create(data, size, format);
88 if (adata) {
89 link = audio_data_link_create(adata);
90 /* This will either return refcount to 1 or clean adata if
91 * cloning failed */
92 audio_data_unref(adata);
93 }
94 return link;
95}
96
97void audio_data_link_destroy(audio_data_link_t *link)
98{
99 assert(link);
100 assert(!link_in_use(&link->link));
101 audio_data_unref(link->adata);
102 free(link);
103}
104
105size_t audio_data_link_available_frames(audio_data_link_t *alink)
106{
107 assert(alink);
108 assert(alink->adata);
109 return pcm_format_size_to_frames(audio_data_link_remain_size(alink),
110 &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;
210}
211
212/**
213 * @}
214 */
Note: See TracBrowser for help on using the repository browser.