975ee8471daa5be7f748726329705b3b59ad87cc
[Faustine.git] / interpretor / lib / src / libsndfile-1.0.25 / src / broadcast.c
1 /*
2 ** Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
3 ** Copyright (C) 2006 Paul Davis <paul@linuxaudiosystems.com>
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU Lesser General Public License as published by
7 ** the Free Software Foundation; either version 2.1 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU Lesser General Public License for more details.
14 **
15 ** You should have received a copy of the GNU Lesser General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #include "sfconfig.h"
21
22 #include <stdio.h>
23 #include <stddef.h>
24 #include <string.h>
25
26 #include "common.h"
27
28
29 static int gen_coding_history (char * added_history, int added_history_max, const SF_INFO * psfinfo) ;
30
31 static inline size_t
32 bc_min_size (const SF_BROADCAST_INFO* info)
33 { if (info == NULL)
34 return 0 ;
35
36 return offsetof (SF_BROADCAST_INFO, coding_history) + info->coding_history_size ;
37 } /* bc_min_size */
38
39 SF_BROADCAST_INFO_16K*
40 broadcast_var_alloc (void)
41 { return calloc (1, sizeof (SF_BROADCAST_INFO_16K)) ;
42 } /* broadcast_var_alloc */
43
44 int
45 broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * info, size_t datasize)
46 { size_t len ;
47
48 if (info == NULL)
49 return SF_FALSE ;
50
51 if (bc_min_size (info) > datasize)
52 { psf->error = SFE_BAD_BROADCAST_INFO_SIZE ;
53 return SF_FALSE ;
54 } ;
55
56 if (datasize >= sizeof (SF_BROADCAST_INFO_16K))
57 { psf->error = SFE_BAD_BROADCAST_INFO_TOO_BIG ;
58 return SF_FALSE ;
59 } ;
60
61 if (psf->broadcast_16k == NULL)
62 { if ((psf->broadcast_16k = broadcast_var_alloc ()) == NULL)
63 { psf->error = SFE_MALLOC_FAILED ;
64 return SF_FALSE ;
65 } ;
66 } ;
67
68 memcpy (psf->broadcast_16k, info, offsetof (SF_BROADCAST_INFO, coding_history)) ;
69
70 psf_strlcpy_crlf (psf->broadcast_16k->coding_history, info->coding_history, sizeof (psf->broadcast_16k->coding_history), datasize - offsetof (SF_BROADCAST_INFO, coding_history)) ;
71 len = strlen (psf->broadcast_16k->coding_history) ;
72
73 if (len > 0 && psf->broadcast_16k->coding_history [len - 1] != '\n')
74 psf_strlcat (psf->broadcast_16k->coding_history, sizeof (psf->broadcast_16k->coding_history), "\r\n") ;
75
76 if (psf->file.mode == SFM_WRITE)
77 { char added_history [256] ;
78
79 gen_coding_history (added_history, sizeof (added_history), &(psf->sf)) ;
80 psf_strlcat (psf->broadcast_16k->coding_history, sizeof (psf->broadcast_16k->coding_history), added_history) ;
81 } ;
82
83 /* Force coding_history_size to be even. */
84 len = strlen (psf->broadcast_16k->coding_history) ;
85 len += (len & 1) ? 1 : 2 ;
86 psf->broadcast_16k->coding_history_size = len ;
87
88 /* Currently writing this version. */
89 psf->broadcast_16k->version = 1 ;
90
91 return SF_TRUE ;
92 } /* broadcast_var_set */
93
94
95 int
96 broadcast_var_get (SF_PRIVATE *psf, SF_BROADCAST_INFO * data, size_t datasize)
97 { size_t size ;
98
99 if (psf->broadcast_16k == NULL)
100 return SF_FALSE ;
101
102 size = SF_MIN (datasize, bc_min_size ((const SF_BROADCAST_INFO *) psf->broadcast_16k)) ;
103
104 memcpy (data, psf->broadcast_16k, size) ;
105
106 return SF_TRUE ;
107 } /* broadcast_var_get */
108
109 /*------------------------------------------------------------------------------
110 */
111
112 static int
113 gen_coding_history (char * added_history, int added_history_max, const SF_INFO * psfinfo)
114 { char chnstr [16] ;
115 int count, width ;
116
117 /*
118 ** From : http://www.sr.se/utveckling/tu/bwf/docs/codhist2.htm
119 **
120 ** Parameter Variable string <allowed option> Unit
121 ** ==========================================================================================
122 ** Coding Algorithm A=<ANALOGUE, PCM, MPEG1L1, MPEG1L2, MPEG1L3,
123 ** MPEG2L1, MPEG2L2, MPEG2L3>
124 ** Sampling frequency F=<11000,22050,24000,32000,44100,48000> [Hz]
125 ** Bit-rate B=<any bit-rate allowed in MPEG 2 (ISO/IEC [kbit/s per channel]
126 ** 13818-3)>
127 ** Word Length W=<8, 12, 14, 16, 18, 20, 22, 24> [bits]
128 ** Mode M=<mono, stereo, dual-mono, joint-stereo>
129 ** Text, free string T=<a free ASCII-text string for in house use.
130 ** This string should contain no commas (ASCII
131 ** 2Chex). Examples of the contents: ID-No; codec
132 ** type; A/D type>
133 */
134
135 switch (psfinfo->channels)
136 { case 0 :
137 return SF_FALSE ;
138
139 case 1 :
140 psf_strlcpy (chnstr, sizeof (chnstr), "mono") ;
141 break ;
142
143 case 2 :
144 psf_strlcpy (chnstr, sizeof (chnstr), "stereo") ;
145 break ;
146
147 default :
148 snprintf (chnstr, sizeof (chnstr), "%uchn", psfinfo->channels) ;
149 break ;
150 } ;
151
152 switch (SF_CODEC (psfinfo->format))
153 { case SF_FORMAT_PCM_U8 :
154 case SF_FORMAT_PCM_S8 :
155 width = 8 ;
156 break ;
157 case SF_FORMAT_PCM_16 :
158 width = 16 ;
159 break ;
160 case SF_FORMAT_PCM_24 :
161 width = 24 ;
162 break ;
163 case SF_FORMAT_PCM_32 :
164 width = 32 ;
165 break ;
166 case SF_FORMAT_FLOAT :
167 width = 24 ; /* Bits in the mantissa + 1 */
168 break ;
169 case SF_FORMAT_DOUBLE :
170 width = 53 ; /* Bits in the mantissa + 1 */
171 break ;
172 case SF_FORMAT_ULAW :
173 case SF_FORMAT_ALAW :
174 width = 12 ;
175 break ;
176 default :
177 width = 42 ;
178 break ;
179 } ;
180
181 count = snprintf (added_history, added_history_max,
182 "A=PCM,F=%u,W=%hu,M=%s,T=%s-%s\r\n",
183 psfinfo->samplerate, width, chnstr, PACKAGE, VERSION) ;
184
185 if (count >= added_history_max)
186 return 0 ;
187
188 return count ;
189 } /* gen_coding_history */
190