1 /*
2  * libPCM by László Szerémi.
3  * Copyright under Boost License.
4  */
5 
6 module libPCM.common;
7 
8 import core.stdc.stdlib;
9 
10 import libPCM.types;
11 
12 /**
13  * Describes the type of codec used, as well as the bitdepth
14  */
15 public enum CodecType : ushort{
16 	NULL			=	0,
17 	UNSIGNED8BIT	=	1,
18 	UNSIGNED12BIT	=	2,
19 	UNSIGNED16BIT	=	3,
20 	UNSIGNED24BIT	=	4,
21 	UNSIGNED32BIT	=	5,
22 	SIGNED8BIT		=	6,
23 	SIGNED12BIT		=	7,
24 	SIGNED16BIT		=	8,
25 	SIGNED24BIT		=	9,
26 	SIGNED32BIT		=	10,
27 	DIALOGIC_ADPCM	=	32,
28 	IMA_ADPCM		=	33,
29 	XA_ADPCM		=	35,
30 	Yamaha_ADPCMA	=	36,
31 	MU_LAW			=	64,
32 	A_LAW_87_6		=	65,
33 	FLOAT			=	96,
34 }
35 
36 /**
37  * For *.wav files
38  */
39 public enum WAVAudioFormat : ushort{
40 	/* WAVE form wFormatTag IDs */
41 	UNKNOWN		=	0x0000, /* Microsoft Corporation */
42 	PCM			=	0x0001,
43 	ADPCM		=	0x0002, /* Microsoft Corporation */
44 	IEEE_FLOAT	=	0x0003, /* Microsoft Corporation */
45 	VSELP		=	0x0004, /* Compaq Computer Corp. */
46 	IBM_CVSD	=	0x0005, /* IBM Corporation */
47 	ALAW		=	0x0006, /* Microsoft Corporation */
48 	MULAW		=	0x0007, /* Microsoft Corporation */
49 	DTS			=	0x0008, /* Microsoft Corporation */
50 	OKI_ADPCM	=	0x0010, /* OKI */
51 	DVI_ADPCM	=	0x0011, /* Intel Corporation */
52 	IMA_ADPCM	=	DVI_ADPCM, /*  Intel Corporation */
53 	MEDIASPACE_ADPCM	=	0x0012, /* Videologic */
54 	SIERRA_ADPCM=	0x0013, /* Sierra Semiconductor Corp */
55 	G723_ADPCM	=	0x0014, /* Antex Electronics Corporation */
56 	DIGISTD		=	0x0015, /* DSP Solutions, Inc. */
57 	DIGIFIX		=	0x0016, /* DSP Solutions, Inc. */
58 	DIALOGIC_OKI_ADPCM	=	0x0017, /* Dialogic Corporation */
59 	MEDIAVISION_ADPCM	=	0x0018, /* Media Vision, Inc. */
60 	CU_CODEC	=	0x0019, /* Hewlett-Packard Company */
61 	YAMAHA_ADPCM=	0x0020, /* Yamaha Corporation of America */
62 	SONARC		=	0x0021, /* Speech Compression */
63 	DSPGROUP_TRUESPEECH	=	0x0022, /* DSP Group, Inc */
64 	ECHOSC1		=	0x0023, /* Echo Speech Corporation */
65 	AUDIOFILE_AF36		=	0x0024, /* Virtual Music, Inc. */
66 	APTX		=	0x0025, /* Audio Processing Technology */
67 	AUDIOFILE_AF10		=	0x0026, /* Virtual Music, Inc. */
68 	PROSODY_1612=	0x0027, /* Aculab plc */
69 	LRC			=	0x0028, /* Merging Technologies S.A. */
70 	DOLBY_AC2	=	0x0030, /* Dolby Laboratories */
71 	GSM610		=	0x0031, /* Microsoft Corporation */
72 	MSNAUDIO	=	0x0032, /* Microsoft Corporation */
73 	ANTEX_ADPCME=	0x0033, /* Antex Electronics Corporation */
74 	CONTROL_RES_VQLPC	=	0x0034, /* Control Resources Limited */
75 	DIGIREAL	=	0x0035, /* DSP Solutions, Inc. */
76 	DIGIADPCM	=	0x0036, /* DSP Solutions, Inc. */
77 	CONTROL_RES_CR10	=	0x0037, /* Control Resources Limited */
78 	NMS_VBXADPCM=	0x0038, /* Natural MicroSystems */
79 	CS_IMAADPCM	=	0x0039, /* Crystal Semiconductor IMA ADPCM */
80 	ECHOSC3		=	0x003A, /* Echo Speech Corporation */
81 	ROCKWELL_ADPCM		=	0x003B, /* Rockwell International */
82 	ROCKWELL_DIGITALK	=	0x003C, /* Rockwell International */
83 	XEBEC		=	0x003D, /* Xebec Multimedia Solutions Limited */
84 	G721_ADPCM	=	0x0040, /* Antex Electronics Corporation */
85 	G728_CELP	=	0x0041, /* Antex Electronics Corporation */
86 	MSG723		=	0x0042, /* Microsoft Corporation */
87 	MPEG		=	0x0050, /* Microsoft Corporation */
88 	RT24		=	0x0052, /* InSoft, Inc. */
89 	PAC			=	0x0053, /* InSoft, Inc. */
90 	MPEGLAYER3	=	0x0055, /* ISO/MPEG Layer3 Format Tag */
91 	LUCENT_G723	=	0x0059, /* Lucent Technologies */
92 	CIRRUS		=	0x0060, /* Cirrus Logic */
93 	ESPCM		=	0x0061, /* ESS Technology */
94 	VOXWARE		=	0x0062, /* Voxware Inc */
95 	CANOPUS_ATRAC		=	0x0063, /* Canopus, co., Ltd. */
96 	G726_ADPCM	=	0x0064, /* APICOM */
97 	G722_ADPCM	=	0x0065, /* APICOM */
98 	DSAT_DISPLAY=	0x0067, /* Microsoft Corporation */
99 	VOXWARE_BYTE_ALIGNED=	0x0069, /* Voxware Inc */
100 	VOXWARE_AC8	=	0x0070, /* Voxware Inc */
101 	VOXWARE_AC10=	0x0071, /* Voxware Inc */
102 	VOXWARE_AC16=	0x0072, /* Voxware Inc */
103 	VOXWARE_AC20=	0x0073, /* Voxware Inc */
104 	VOXWARE_RT24=	0x0074, /* Voxware Inc */
105 	VOXWARE_RT29=	0x0075, /* Voxware Inc */
106 	VOXWARE_RT29HW		=	0x0076, /* Voxware Inc */
107 	VOXWARE_VR12=	0x0077, /* Voxware Inc */
108 	VOXWARE_VR18=	0x0078, /* Voxware Inc */
109 	VOXWARE_TQ40=	0x0079, /* Voxware Inc */
110 	SOFTSOUND	=	0x0080, /* Softsound, Ltd. */
111 	VOXWARE_TQ60=	0x0081, /* Voxware Inc */
112 	MSRT24		=	0x0082, /* Microsoft Corporation */
113 	G729A		=	0x0083, /* AT&T Labs, Inc. */
114 	MVI_MVI2	=	0x0084, /* Motion Pixels */
115 	DF_G726		=	0x0085, /* DataFusion Systems (Pty) (Ltd) */
116 	DF_GSM610	=	0x0086, /* DataFusion Systems (Pty) (Ltd) */
117 	ISIAUDIO	=	0x0088, /* Iterated Systems, Inc. */
118 	ONLIVE		=	0x0089, /* OnLive! Technologies, Inc. */
119 	SBC24		=	0x0091, /* Siemens Business Communications Sys */
120 	DOLBY_AC3_SPDIF		=	0x0092, /* Sonic Foundry */
121 	MEDIASONIC_G723		=	0x0093, /* MediaSonic */
122 	PROSODY_8KBPS		=	0x0094, /* Aculab plc */
123 	ZYXEL_ADPCM	=	0x0097, /* ZyXEL Communications, Inc. */
124 	PHILIPS_LPCBB		=	0x0098, /* Philips Speech Processing */
125 	PACKED		=	0x0099, /* Studer Professional Audio AG */
126 	MALDEN_PHONYTALK	=	0x00A0, /* Malden Electronics Ltd. */
127 	RHETOREX_ADPCM		=	0x0100, /* Rhetorex Inc. */
128 	IRAT		=	0x0101, /* BeCubed Software Inc. */
129 	VIVO_G723	=	0x0111, /* Vivo Software */
130 	VIVO_SIREN	=	0x0112, /* Vivo Software */
131 	DIGITAL_G723=	0x0123, /* Digital Equipment Corporation */
132 	SANYO_LD_ADPCM		=	0x0125, /* Sanyo Electric Co., Ltd. */
133 	SIPROLAB_ACEPLNET	=	0x0130, /* Sipro Lab Telecom Inc. */
134 	SIPROLAB_ACELP4800	=	0x0131, /* Sipro Lab Telecom Inc. */
135 	SIPROLAB_ACELP8V3	=	0x0132, /* Sipro Lab Telecom Inc. */
136 	SIPROLAB_G729		=	0x0133, /* Sipro Lab Telecom Inc. */
137 	SIPROLAB_G729A		=	0x0134, /* Sipro Lab Telecom Inc. */
138 	SIPROLAB_KELVIN		=	0x0135, /* Sipro Lab Telecom Inc. */
139 	G726ADPCM	=	0x0140, /* Dictaphone Corporation */
140 	QUALCOMM_PUREVOICE	=	0x0150, /* Qualcomm, Inc. */
141 	QUALCOMM_HALFRATE	=	0x0151, /* Qualcomm, Inc. */
142 	TUBGSM		=	0x0155, /* Ring Zero Systems, Inc. */
143 	MSAUDIO1	=	0x0160, /* Microsoft Corporation */
144 	CREATIVE_ADPCM		=	0x0200, /* Creative Labs, Inc */
145 	CREATIVE_FASTSPEECH8=	0x0202, /* Creative Labs, Inc */
146 	CREATIVE_FASTSPEECH10	=	0x0203, /* Creative Labs, Inc */
147 	UHER_ADPCM	=	0x0210, /* UHER informatic GmbH */
148 	QUARTERDECK	=	0x0220, /* Quarterdeck Corporation */
149 	ILINK_VC	=	0x0230, /* I-link Worldwide */
150 	RAW_SPORT	=	0x0240, /* Aureal Semiconductor */
151 	IPI_HSX		=	0x0250, /* Interactive Products, Inc. */
152 	IPI_RPELP	=	0x0251, /* Interactive Products, Inc. */
153 	CS2			=	0x0260, /* Consistent Software */
154 	SONY_SCX	=	0x0270, /* Sony Corp. */
155 	FM_TOWNS_SND=	0x0300, /* Fujitsu Corp. */
156 	BTV_DIGITAL	=	0x0400, /* Brooktree Corporation */
157 	QDESIGN_MUSIC		=	0x0450, /* QDesign Corporation */
158 	VME_VMPCM	=	0x0680, /* AT&T Labs, Inc. */
159 	TPC			=	0x0681, /* AT&T Labs, Inc. */
160 	OLIGSM		=	0x1000, /* Ing C. Olivetti & C., S.p.A. */
161 	OLIADPCM	=	0x1001, /* Ing C. Olivetti & C., S.p.A. */
162 	OLICELP		=	0x1002, /* Ing C. Olivetti & C., S.p.A. */
163 	OLISBC		=	0x1003, /* Ing C. Olivetti & C., S.p.A. */
164 	OLIOPR		=	0x1004, /* Ing C. Olivetti & C., S.p.A. */
165 	LH_CODEC	=	0x1100, /* Lernout & Hauspie */
166 	WAVE_FORMAT_NORRIS	=	0x1400, /* Norris Communications, Inc. */
167 	SOUNDSPACE_MUSICOMPRESS	=	0x1500, /* AT&T Labs, Inc. */
168 	DVM		=	0x2000, /* FAST Multimedia AG */
169 }
170 
171 public CodecType fromWAVAudioFormat(ushort input, ushort bitDepth){
172 	switch(input){
173 		case WAVAudioFormat.PCM:
174 			switch (bitDepth){
175 				case 8:
176 					return CodecType.UNSIGNED8BIT;
177 				case 16:
178 					return CodecType.SIGNED16BIT;
179 				default:
180 					return CodecType.NULL;
181 			}
182 		case WAVAudioFormat.OKI_ADPCM:
183 			return CodecType.DIALOGIC_ADPCM;
184 		case WAVAudioFormat.IMA_ADPCM:
185 			return CodecType.IMA_ADPCM;
186 		case WAVAudioFormat.IEEE_FLOAT:
187 			return CodecType.FLOAT;
188 		default:
189 			return CodecType.NULL;
190 	}
191 }
192 
193 public class AudioFileException : Exception{
194 	@nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
195     {
196         super(msg, file, line, next);
197     }
198 
199     @nogc @safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
200     {
201         super(msg, file, line, next);
202     }
203 }
204 
205 
206 	/**
207 	 * Returns the word lenght for the given codec type
208 	 */
209 public @nogc int getWordLength(CodecType codec){
210 	switch(codec){
211 		//case CodecType.A_LAW_87_6, CodecType.MU_LAW, CodecType.SIGNED8BIT, CodecType.UNSIGNED8BIT: return 8;
212 		//case CodecType.DIALOGIC_ADPCM, CodecType.IMA_ADPCM: return 4;
213 		case CodecType.SIGNED16BIT, CodecType.UNSIGNED16BIT: return 16;
214 		case CodecType.SIGNED24BIT, CodecType.UNSIGNED24BIT: return 24;
215 		case CodecType.SIGNED32BIT, CodecType.UNSIGNED32BIT, CodecType.FLOAT: return 32;
216 		//case CodecType.COMPACT_ADPCM: return 2;
217 		case CodecType.XA_ADPCM: return 128 * 8;
218 		default: return 8;
219 	}
220 }
221 	/**
222 	 * Completely deallocates the memory for the given PCM data
223 	 */
224 	/*void deletePCMFromMemory(PCMFile* file){
225 		if(file.name){
226 			free(file.name);
227 		}
228 		if(file.startOfData){
229 			free(file.startOfData);
230 		}else{
231 			for(int i ; i < file.header.numOfChannels ; i++){
232 				free((*file.waveData + i).data);
233 				free(file.waveData + i);
234 			}
235 		}
236 		free(file);
237 	}*/
238 /**
239  * Separates audio streams from a joint stream.
240  */
241 public @nogc void separateAudioChannels(void* input, void*[8] output, uint lenght, int channels, int wordLength = 16){
242 	switch(wordLength){
243 		case 16:
244 			ushort* input0 = cast(ushort*)input;
245 			ushort*[8] output0 = cast(ushort*[8])output;
246 			for(uint i ; i < lenght ; i++){
247 				for(int j ; j < channels ; j++){
248 					output0[j][i] = input0[(i * channels) + j];
249 				}
250 			}
251 			break;
252 		case 8:
253 			ubyte* input0 = cast(ubyte*)input;
254 			ubyte*[8] output0 = cast(ubyte*[8])output;
255 			for(uint i ; i < lenght ; i++){
256 				for(int j ; j < channels ; j++){
257 					output0[j][i] = input0[(i * channels) + j];
258 				}
259 			}
260 			break;
261 		case 32:
262 			uint* input0 = cast(uint*)input;
263 			uint*[8] output0 = cast(uint*[8])output;
264 			for(uint i ; i < lenght ; i++){
265 				for(int j ; j < channels ; j++){
266 					output0[j][i] = input0[(i * channels) + j];
267 				}
268 			}
269 			break;
270 		default:
271 			if(!(wordLength % 8)){
272 				ubyte* input0 = cast(ubyte*)input;
273 				ubyte*[8] output0 = cast(ubyte*[8])output;
274 				for(uint i ; i < lenght ; i++){
275 					for(int j ; j < channels ; j++){
276 						for(int k ; k < wordLength / 8 ; k++){
277 							output0[j][i+k] = input0[(i * channels) + j + k];
278 						}
279 					}
280 				}
281 			}
282 			break;
283 	}
284 }
285 /**
286  * Joints multiple audio channels into a single one.
287  */
288 public @nogc void joinAudioChannels(void*[8] input, void* output, uint lenght, int channels, int wordLength = 16){
289 	switch(wordLength){
290 		case 16:
291 			ushort* output0 = cast(ushort*)output; 
292 			ushort*[8] input0 = cast(ushort*[8])input;
293 			for(uint i ; i < lenght ; i++){
294 				for(int j ; j < channels ; j++){
295 					output0[(i * channels) + j] = input0[j][i];
296 				}
297 			}
298 			break;
299 		case 8:
300 			ubyte* output0 = cast(ubyte*)output; 
301 			ubyte*[8] input0 = cast(ubyte*[8])input;
302 			for(uint i ; i < lenght ; i++){
303 				for(int j ; j < channels ; j++){
304 					output0[(i * channels) + j] = input0[j][i];
305 				}
306 			}
307 			break;
308 		case 32:
309 			uint* output0 = cast(uint*)output;
310 			uint*[8] input0 = cast(uint*[8])input;
311 			for(uint i ; i < lenght ; i++){
312 				for(int j ; j < channels ; j++){
313 					output0[(i * channels) + j] = input0[j][i];
314 				}
315 			}
316 			break;
317 		default:
318 			if(!(wordLength % 8)){
319 				ubyte* output0 = cast(ubyte*)output; 
320 				ubyte*[8] input0 = cast(ubyte*[8])input;
321 				for(uint i ; i < lenght ; i++){
322 					for(int j ; j < channels ; j++){
323 						for(int k ; k < wordLength / 8 ; k++){
324 							output0[(i * channels) + j + k] = input0[j][i+k];
325 						}
326 					}
327 				}
328 			}
329 			break;
330 	}
331 }