source: roaraudio/roard/codecfilter_wave.c @ 5878:3b92b0d6ef9b

Last change on this file since 5878:3b92b0d6ef9b was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

File size: 7.3 KB
Line 
1//codecfilter_wave.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2013
5 *
6 *  This file is part of roard a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  RoarAudio is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 */
25
26#include "roard.h"
27
28#ifndef ROAR_WITHOUT_CF_WAVE
29
30int cf_wave_open(CODECFILTER_USERDATA_T * inst, int codec,
31                                            struct roar_stream_server * info,
32                                            struct roar_codecfilter   * filter) {
33 struct codecfilter_wave_inst * self = roar_mm_malloc(sizeof(struct codecfilter_wave_inst));
34 struct roar_stream * s = ROAR_STREAM(info);
35
36 if ( !self )
37  return -1;
38
39 self->stream               = info;
40 self->vstream              = NULL;
41 self->opened               = 0;
42
43 *inst = (CODECFILTER_USERDATA_T) self;
44
45 memcpy(&(s->info), g_sa, sizeof(struct roar_audio_info));
46 return 0;
47}
48
49int cf_wave_close(CODECFILTER_USERDATA_T   inst) {
50// struct codecfilter_wave_inst * self = (struct codecfilter_wave_inst *) inst;
51
52 if ( !inst )
53  return -1;
54
55 roar_mm_free(inst);
56 return 0;
57}
58
59int cf_wave_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
60 struct codecfilter_wave_inst * self = (struct codecfilter_wave_inst *) inst;
61 int r = -1;
62 char tbuf[44];
63 struct roar_stream * ps = ROAR_STREAM(self->stream);
64 struct roar_stream *  s;
65 struct roar_audio_info info;
66 uint16_t tmp16;
67 uint32_t tmp32;
68 int codec = -1;
69 int vid, fh;
70
71 if ( self->opened ) {
72  return stream_vio_s_read(self->stream, buf, len);
73 } else {
74  if (stream_vio_s_read(self->stream, tbuf, 44) != 44) {
75   return -1;
76  }
77
78  // test the header, is this really a RIFF WAVE stream?
79  if ( strncmp(tbuf, "RIFF", 4) != 0 )
80   return -1;
81
82  if ( strncmp(tbuf+8, "WAVEfmt ", 8) != 0 )
83   return -1;
84
85  if ( strncmp(tbuf+36, "data", 4) != 0 )
86   return -1;
87
88  // TODO: write better code here!
89
90  if ( (fh = streams_get_fh(ps->id)) == -1 ) {
91   return -1;
92  }
93
94  if ( (vid = streams_new_virtual(ps->id, &(self->vstream))) == -1 ) {
95   return -1;
96  }
97
98  ROAR_DBG("cf_wave_read(*): self->vstream=%p", self->vstream);
99
100  s = ROAR_STREAM(self->vstream);
101
102  memcpy(&tmp32, tbuf+24, 4);
103  s->info.rate = ROAR_LE2HOST32(tmp32);
104
105  memcpy(&tmp16, tbuf+22, 2);
106  s->info.channels = ROAR_LE2HOST16(tmp16);
107
108  memcpy(&tmp16, tbuf+34, 2);
109  s->info.bits = ROAR_LE2HOST16(tmp16);
110
111  memcpy(&tmp16, tbuf+20, 2);
112
113  switch (ROAR_LE2HOST16(tmp16)) {
114   case ROAR_RIFF_WAVE_CID_PCM:
115     if ( s->info.bits == 8 ) {
116      codec = ROAR_CODEC_PCM_U_LE;
117     } else {
118      codec = ROAR_CODEC_PCM_S_LE;
119     }
120    break;
121   case ROAR_RIFF_WAVE_CID_ALAW:
122     codec = ROAR_CODEC_ALAW;
123    break;
124   case ROAR_RIFF_WAVE_CID_MULAW:
125     codec = ROAR_CODEC_MULAW;
126    break;
127   case ROAR_RIFF_WAVE_CID_RSOUND:
128     memcpy(&tmp16, tbuf+42, 2);
129     switch (ROAR_LE2HOST16(tmp16)) {
130      case ROAR_RIFF_WAVE_RSID_S16_LE:
131        s->info.bits = 16;
132        codec        = ROAR_CODEC_PCM_S_LE;
133       break;
134      case ROAR_RIFF_WAVE_RSID_S16_BE:
135        s->info.bits = 16;
136        codec        = ROAR_CODEC_PCM_U_BE;
137       break;
138      case ROAR_RIFF_WAVE_RSID_U16_LE:
139        s->info.bits = 16;
140        codec        = ROAR_CODEC_PCM_U_LE;
141       break;
142      case ROAR_RIFF_WAVE_RSID_U16_BE:
143        s->info.bits = 16;
144        codec        = ROAR_CODEC_PCM_U_BE;
145       break;
146      case ROAR_RIFF_WAVE_RSID_S8:
147        s->info.bits = 8;
148        codec        = ROAR_CODEC_PCM_S_LE;
149       break;
150      case ROAR_RIFF_WAVE_RSID_U8:
151        s->info.bits = 8;
152        codec        = ROAR_CODEC_PCM_U_LE;
153       break;
154      default:
155        return -1;
156     }
157    break;
158   case ROAR_RIFF_WAVE_CID_IEEE_FLOAT:
159   default:
160     return -1;
161  }
162
163   s->info.codec            = codec;
164  self->vstream->codec_orgi = codec;
165
166  memcpy(&info, &(s->info), sizeof(struct roar_audio_info));
167
168  if ( streams_set_fh(vid, fh) == -1 ) {
169   return -1;
170  }
171
172/*
173  if ( roar_vio_open_pass(&(self->vstream->vio), &(self->stream->vio)) == -1 ) {
174   return -1;
175  }
176*/
177
178  memcpy(&(self->vstream->vio), &(self->stream->vio), sizeof(struct roar_vio_calls));
179
180  if ( streams_set_null_io(ps->id) == -1 ) {
181   return -1;
182  }
183
184  memcpy(&(ps->info), &info, sizeof(struct roar_audio_info));
185
186  self->opened = 1;
187
188  errno = EAGAIN;
189  return -1;
190 }
191
192 return r;
193}
194
195int cf_wave_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
196 struct codecfilter_wave_inst * self = (struct codecfilter_wave_inst *) inst;
197 struct roar_stream           * s    = ROAR_STREAM(self->stream);
198 void   * header;
199 int32_t  tmp32;
200 int16_t  tmp16;
201 int16_t  bits;
202 int16_t  codec;
203 int      sid;
204
205 ROAR_DBG("cf_wave_write(inst=%p, buf=%p, len=%i) = ?", inst, buf, len);
206 ROAR_DBG("cf_wave_write(inst=%p, buf=%p, len=%i): self->opened=%i", inst, buf, len, self->opened);
207
208 if ( self->opened ) {
209  return stream_vio_s_write(self->stream, buf, len);
210 } else {
211
212  if ( s->fh == -1 ) {
213   errno = EAGAIN;
214   return -1;
215  }
216
217  sid = ROAR_STREAM(self->stream)->id;
218
219  if ( stream_prethru_destroy(sid) == -1 ) {
220   return -1;
221  }
222
223  if ( stream_prethru_add_data(sid, &header, 44) == -1 ) {
224   return -1;
225  }
226
227  memcpy(header   , "RIFF\367\377\377\177WAVEfmt \020", 17);
228  memcpy(header+36, "data\313\377\377\177", 8);
229
230  switch (s->info.codec) {
231   case ROAR_CODEC_PCM_S_LE:
232     codec = 0x0001;
233    break;
234   default:
235     ROAR_ERR("cf_wave_write(*) Codec not supported!");
236     return -1;
237    break;
238  }
239
240  ROAR_DBG("cf_wave_write(*) Codec supported!");
241
242  bits = s->info.bits;
243  memcpy(header+24, &(s->info.rate    ), 4);
244  memcpy(header+22, &(s->info.channels), 2);
245  memcpy(header+34, &bits, 2);
246
247  tmp16 = s->info.channels * bits / 8;
248  memcpy(header+32, &tmp16, 2);
249  tmp32 = tmp16 * s->info.rate;
250  memcpy(header+28, &tmp32, 4);
251  memcpy(header+20, &codec, 2);
252
253  if ( stream_vio_s_write(self->stream, header, 44) != 44 )
254   return -1;
255
256  self->opened = 1;
257
258  errno = EAGAIN;
259//  return -1;
260
261  len = stream_vio_s_write(self->stream, buf, len);
262
263  cf_wave_close(inst);
264  ROAR_STREAM_SERVER(s)->codecfilter = -1;
265
266  return len;
267
268//  return stream_vio_s_write(self->stream, buf, len);
269 }
270
271 return -1;
272}
273
274int cf_wave_ctl(CODECFILTER_USERDATA_T   inst, int cmd, void * data) {
275 struct codecfilter_wave_inst * self = (struct codecfilter_wave_inst *) inst;
276 int_least32_t type = cmd & ROAR_STREAM_CTL_TYPEMASK;
277
278 cmd -= type;
279
280 ROAR_DBG("cf_wave_ctl(*): command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
281                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
282
283 switch (cmd) {
284  case ROAR_CODECFILTER_CTL2CMD(ROAR_CODECFILTER_CTL_VIRTUAL_DELETE):
285    streams_delete(ROAR_STREAM(self->stream)->id);
286    return 0;
287   break;
288  default:
289    ROAR_DBG("cf_wave_ctl(*): Unknown command: cmd=0x%.8x, type=0x%.8x, pcmd=0x%.8x",
290                    cmd, type, ROAR_CODECFILTER_CTL2CMD(cmd));
291    return -1;
292 }
293
294 return -1;
295}
296
297#endif
298
299//ll
Note: See TracBrowser for help on using the repository browser.