1 /*
2  * @(#)AudioFormatMPA.java - parse Audioheaders, mpa, incl. RDS
3  *
4  * Copyright (c) 2003-2008 by dvb.matt, All Rights Reserved.
5  *
6  * This file is part of ProjectX, a free Java based demux utility.
7  * By the authors, ProjectX is intended for educational purposes only,
8  * as a non-commercial test project.
9  *
10  * The part of audio parsing was derived from the MPEG/Audio
11  * Software Simulation Group's audio codec and ATSC A/52 in a special modified manner.
12  *
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27  *
28  */
29 
30 package net.sourceforge.dvb.projectx.audio;
31 
32 import java.util.Arrays;
33 import java.util.ArrayList;
34 
35 import java.io.IOException;
36 import java.io.ByteArrayOutputStream;
37 import java.io.FileOutputStream;
38 import java.io.BufferedOutputStream;
39 
40 import net.sourceforge.dvb.projectx.common.Common;
41 
42 
43 public class AudioFormatMPA extends AudioFormat {
44 
45 	private String instanced_time = "";
46 
47 	private MpaConverter MPAConverter;
48 
AudioFormatMPA()49 	public AudioFormatMPA()
50 	{
51 		super();
52 
53 		instanced_time = String.valueOf(System.currentTimeMillis());
54 
55 		initCRCTable();
56 	}
57 
58 	private int CRC16_POLY = 0x18005; //((1 << 0) | (1 << 2) | (1 << 15) | (1 << 16));
59 
60 	private int[] crc_table = new int[256];
61 
62 	private int[][][] bitrate_index = {{
63 		{-1,8000,16000,24000,32000,40000,48000,56000,64000,
64 		80000,96000,112000,128000,144000,160000,0 },		//MPG-2, L3
65 		{-1,8000,16000,24000,32000,40000,48000,56000,64000,
66 		80000,96000,112000,128000,144000,160000,0 },		//MPG-2, L2
67 		{-1,32000,48000,56000,64000,80000,96000,112000,128000,
68 		144000,160000,176000,192000,224000,256000,0 }		//MPG-2, L1
69 	},{
70 		{-1,32000,40000,48000,56000,64000,80000,96000,
71 		112000,128000,160000,192000,224000,256000,320000, 0 },	//MPG-1, L3
72 		{-1,32000,48000,56000,64000,80000,96000,112000,
73 		128000,160000,192000,224000,256000,320000,384000, 0 },	//MPG-1, L2
74 		{-1,32000,64000,96000,128000,160000,192000,224000,
75 		256000,288000,320000,352000,384000,416000,448000,0 }	//MPG-1, L1
76 	},{
77 		{-1, 6000, 8000, 10000, 12000, 16000, 20000, 24000,    //MPG-2.5, L3??
78 		28000, 320000, 40000, 48000, 56000, 64000, 80000, 0 },
79 		{-1, 6000, 8000, 10000, 12000, 16000, 20000, 24000,    //MPG-2.5, L2
80 		28000, 320000, 40000, 48000, 56000, 64000, 80000, 0 },
81 		{-1, 8000, 12000, 16000, 20000, 24000, 32000, 40000,    //MPG-2.5, L1
82 		48000, 560000, 64000, 80000, 96000, 112000, 128000, 0 }
83 	}};
84 
85 	private int frequency_index[][] = {
86 		{ 22050,24000,16000,0 },	//MPG2 - 22.05,24,16khz
87 		{ 44100,48000,32000,0 },	//MPG1 - 44.1 ,48,32khz
88 		{ 11025,12000,8000,0 }		//MPG2.5 - 11.025,12,8khz
89 	};
90 
91 	private double time_index[] = { 0.0,103680000.0,103680000.0,34560000.0 };	//L3,L2,L1 * 90
92 
93 	private String[] dID = { "MPEG-2", "MPEG-1", "MPEG-2.5" };
94 	private String[] dLayer = { "n.a.", "Layer3", "Layer2", "Layer1" };
95 	private String[] dCRC = { "noCRC", "CRC" };
96 	private String[] dMode = { "stereo", "jstereo", "dual", "mono" };
97 
98 	private int Bound = 0;
99 	private int Sblimit = 32;
100 
101 	/**
102 	 * parse mpa Header
103 	 */
parseHeader(byte[] frame, int pos)104 	public int parseHeader(byte[] frame, int pos)
105 	{
106 		int sblimit = 32;
107 
108 		if ( (0xFF & frame[pos]) != 0xFF || (0xF0 & frame[pos + 1]) != 0xF0 )
109 			return -1;
110 
111 		setID(1 & frame[pos + 1]>>>3);
112 		setEmphasis(3 & frame[pos + 3]);
113 
114 		if (getID() == 1 && getEmphasis() == 2)
115 			setID(2);
116 
117 		setLayer(3 & frame[pos + 1]>>>1);
118 
119 		if (getLayer() < 1)
120 			return -2;
121 
122 		setProtectionBit((1 & frame[pos + 1]) ^ 1);
123 
124 		setBitrate(bitrate_index[getID()][getLayer() - 1][0xF & frame[pos + 2]>>>4]);
125 
126 		if (getBitrate() < 1)
127 			return -3;
128 
129 		setSamplingFrequency(frequency_index[getID()][3 & frame[pos + 2]>>>2]);
130 
131 		if (getSamplingFrequency() == 0)
132 			return -4;
133 
134 		setPaddingBit(1 & (frame[pos + 2]>>>1));
135 		setPrivateBit(1 & frame[pos + 2]);
136 
137 		setMode(3 & frame[pos + 3]>>>6);
138 		setModeExtension(3 & frame[pos + 3]>>>4);
139 
140 		if (getMode() == 0)
141 			setModeExtension(0);
142 
143 		Bound = getMode() == 1 ? ((getModeExtension() + 1) << 2) : sblimit;
144 		setChannel(getMode() == 3 ? 1 : 2);
145 		setCopyright(1 & frame[pos + 3]>>>3);
146 		setOriginal(1 & frame[pos + 3]>>>2);
147 		setFrameTimeLength(time_index[getLayer()] / getSamplingFrequency());
148 
149 		if (getID() == 1 && getLayer() == 2)   // MPEG-1, L2 restrictions
150 		{
151 			if (getBitrate() / getChannel() < 32000)
152 				return -5; /* unsupported bitrate */
153 
154 			if (getBitrate() / getChannel() > 192000)
155 				return -6; /* unsupported bitrate */
156 
157 			if (getBitrate() / getChannel() < 56000)
158 			{
159 				if(getSamplingFrequency() == 32000)
160 					Sblimit = 12;
161 				else
162 					Sblimit = 8;
163 			}
164 
165 			else if (getBitrate() / getChannel() < 96000)
166 				Sblimit = 27;
167 
168 			else
169 			{
170 				if (getSamplingFrequency() == 48000)
171 					Sblimit = 27;
172 				else
173 					Sblimit = 30;
174 			}
175 
176 			if (Bound > Sblimit)
177 				Bound = Sblimit;
178 		}
179 
180 		else if (getLayer() == 2)  // MPEG-2
181 		{
182 			Sblimit = 30;
183 		}
184 
185 		if (getLayer() < 3)
186 		{
187 			if (Bound > Sblimit)
188 				Bound = Sblimit;
189 
190 			setSizeBase((getID() == 0 && getLayer() == 1 ? 72 : 144) * getBitrate() / getSamplingFrequency());
191 			setSize(getSizeBase() + getPaddingBit());
192 
193 			return 1;
194 		}
195 
196 		else
197 		{
198 			Sblimit = 32;
199 			setSizeBase((12 * getBitrate() / getSamplingFrequency())<<2);
200 			setSize(getSizeBase() + (getPaddingBit()<<2));
201 
202 			return 2;
203 		}
204 	}
205 
206 	/**
207 	 * parse next mpa Header
208 	 */
parseNextHeader(byte[] frame, int pos)209 	public int parseNextHeader(byte[] frame, int pos)
210 	{
211 
212 		if ( (0xFF & frame[pos]) != 0xFF || (0xF0 & frame[pos + 1]) != 0xF0 )
213 			return -1;
214 
215 		setNextID(1 & frame[pos + 1]>>>3);
216 		setNextEmphasis(3 & frame[pos + 3]);
217 
218 		if (getNextID() == 1 && getNextEmphasis() == 2)
219 			setNextID(2);
220 
221 		setNextLayer(3 & frame[pos + 1]>>>1);
222 
223 		if (getNextLayer() < 1)
224 			return -2;
225 
226 		setNextProtectionBit((1 & frame[pos + 1]) ^ 1);
227 
228 		setNextBitrate(bitrate_index[getNextID()][getNextLayer() - 1][0xF & frame[pos + 2]>>>4]);
229 
230 		if (getNextBitrate() < 1)
231 			return -3;
232 
233 		setNextSamplingFrequency(frequency_index[getNextID()][3 & frame[pos + 2]>>>2]);
234 
235 		if (getNextSamplingFrequency() == 0)
236 			return -4;
237 
238 		setNextPaddingBit(1 & (frame[pos + 2]>>>1));
239 		setNextPrivateBit(1 & frame[pos + 2]);
240 
241 		setNextMode(3 & frame[pos + 3]>>>6);
242 		setNextModeExtension(3 & frame[pos + 3]>>>4);
243 
244 		if (getNextMode() == 0)
245 			setNextModeExtension(0);
246 
247 		setNextChannel(getNextMode() == 3 ? 1 : 2);
248 		setNextCopyright(1 & frame[pos + 3]>>>3);
249 		setNextOriginal(1 & frame[pos + 3]>>>2);
250 		setNextFrameTimeLength(time_index[getNextLayer()] / getNextSamplingFrequency());
251 
252 		if (getNextID() == 1 && getNextLayer() == 2)   // MPEG-1, L2 restrictions
253 		{
254 			if (getNextBitrate() / getNextChannel() < 32000)
255 				return -5; /* unsupported bitrate */
256 
257 			if (getNextBitrate() / getNextChannel() > 192000)
258 				return -6; /* unsupported bitrate */
259 		}
260 
261 		if (getNextLayer() < 3)
262 		{
263 			setNextSizeBase((getNextID() == 0 && getNextLayer() == 1 ? 72 : 144) * getNextBitrate() / getNextSamplingFrequency());
264 			setNextSize(getNextSizeBase() + getNextPaddingBit());
265 
266 			return 1;
267 		}
268 
269 		else
270 		{
271 			setNextSizeBase((12 * getNextBitrate() / getNextSamplingFrequency())<<2);
272 			setNextSize(getNextSizeBase() + (getNextPaddingBit()<<2));
273 
274 			return 2;
275 		}
276 	}
277 
278 	/**
279 	 * compare current & last mpa header
280 	 */
compareHeader()281 	public int compareHeader()
282 	{
283 		if (getLastID() != getID())
284 			return 0x1;
285 
286 		else if (getLastLayer() != getLayer())
287 			return 0x2;
288 
289 		else if (getLastSamplingFrequency() != getSamplingFrequency())
290 			return 0x4;
291 
292 		else if (getLastBitrate() != getBitrate())
293 			return 0x8;
294 
295 		else if (getLastProtectionBit() != getProtectionBit())
296 			return 0x10;
297 
298 		else if (getLastMode() != getMode())
299 		{
300 			if (getMode() + getLastMode() < 2)
301 				return 0x20;
302 
303 			else
304 				return 0x40;
305 		}
306 
307 		else
308 			return 0;
309 	}
310 
311 	/**
312 	 * display last mpa header
313 	 */
displayHeader()314 	public String displayHeader()
315 	{
316 		return ("" + dID[getLastID()] + ", " + dLayer[getLastLayer()] + ", " + getLastSamplingFrequency() + "Hz, " + dMode[getLastMode()] + ", "+ (getLastBitrate() / 1000) + "kbps, " + dCRC[getLastProtectionBit()]);
317 	}
318 
319 	/**
320 	 * link to mpa conversion
321 	 */
convertFrame(byte[] frame, int mode)322 	public byte[][] convertFrame(byte[] frame, int mode)
323 	{
324 		if (MPAConverter == null)
325 			MPAConverter = new MpaConverter();
326 
327 		byte[][] newframes = MPAConverter.modifyframe(frame, mode);
328 
329 		parseRiffData(newframes[0], 1);
330 
331 		if (mode >= MpaConverter.SPLIT_INTO_SINGLE)
332 			parseRiffData(newframes[1], 2);
333 
334 		return newframes;
335 	}
336 
337 	/**
338 	 * edit frame
339 	 */
340 /**	public byte[] editFrame(byte[] frame, int mode)
341 	{
342 		return frame;
343 	}
344 **/
345 
346 	/**
347 	 * link to mpa decoder
348 	 */
349 /**	public byte[] decodeFrame(byte[] frame, int mode)
350 	{
351 		if (MPADecoder == null)
352 			MPADecoder = new MpaDecoder();
353 
354 		return MPADecoder.decodeArray(frame);
355 	}
356 **/
357 
358 	/**
359 	 * remove CRC from mpa
360 	 **/
removeCRC(byte[] frame, boolean remove)361 	public void removeCRC(byte[] frame, boolean remove)
362 	{
363 		if (getLayer() < 2 || !remove)
364 			return;
365 
366 		removePrivateBit(frame);
367 
368 		if ((frame[1] & 1) == 1)
369 			return;
370 
371 		System.arraycopy(frame, 6, frame, 4, frame.length - 6);
372 		Arrays.fill(frame, frame.length - 2, frame.length, (byte) 0);
373 
374 		frame[1] |= 1;
375 
376 		setProtectionBit(1);
377 	}
378 
379 	/**
380 	 * remove private Bit from mpa
381 	 **/
removePrivateBit(byte[] frame)382 	private void removePrivateBit(byte[] frame)
383 	{
384 		if ( (frame[2] & 1) == 0)
385 			return;
386 
387 		frame[2] &= ~1;
388 
389 		setPrivateBit(0);
390 	}
391 
392 	/**
393 	 * crc init table
394 	 */
initCRCTable()395 	private void initCRCTable()
396 	{
397 		for (int n = 0, c, k; n < 256; n++)
398 		{
399 			c = n << 8;
400 
401 			for (k = 0; k < 8; k++)
402 			{
403 				if ((c & (1 << 15)) != 0)
404 					c = ((c << 1) & 0xFFFF) ^ (CRC16_POLY & 0xFFFF);
405 
406 				else
407 					c = c << 1;
408 			}
409 
410 			crc_table[n] = c;
411 		}
412 	}
413 
414 	/**
415 	 * crc
416 	 */
determineCRC(byte[] data, int offs, int len, int crc)417 	private int determineCRC(byte[] data, int offs, int len, int crc)
418 	{
419 		int end = offs + (len>>>3);
420 
421 		for (int i = offs; i < end; i++)
422 			crc = (crc_table[(0xFF & data[i]) ^ (crc >> 8)] ^ (crc << 8)) & 0xFFFF;
423 
424 		int remaining_bits = len & 7;
425 
426 		if (remaining_bits > 0)
427 			crc = (crc_table[((0xFF >> (8 - remaining_bits)) & (data[end] >> (8 - remaining_bits))) ^ (crc >> (16 - remaining_bits))] ^ (crc << remaining_bits)) & 0xFFFF;
428 
429 		return crc;
430 	}
431 
432 	/**
433 	 *
434 	 */
validateCRC(byte[] _data, int offs, int len)435 	public int validateCRC(byte[] _data, int offs, int len)
436 	{
437 		if (getLayer() < 2 || getProtectionBit() == 0)
438 			return 0;
439 
440 		int crc_val = (0xFF & _data[4])<<8 | (0xFF & _data[5]);
441 
442 		byte[] data = new byte[_data.length];
443 		System.arraycopy(_data, 0, data, 0, 4);
444 		System.arraycopy(_data, 6, data, 4, _data.length - 6);
445 
446 		int ch, sb, offset = 2, nr_bits = 16, BitPos[] = { 32 };
447 
448 		if (getLayer() == 3) // BAL only, of 32 subbands
449 		{
450 			for( sb=0; sb<Bound; sb++)
451 				for( ch=0; ch<getChannel(); ch++)
452 					nr_bits += 4;
453 
454 			for( sb=Bound; sb<Sblimit; sb++)
455 				nr_bits += 4;
456 		}
457 		else // BAL and SCFSI, of various subbands
458 		{
459 			int table_nbal[];
460 			int table_alloc[][];
461 			int allocation[][] = new int[32][2];
462 
463 			if (getID()==1)
464 			{
465 				if (Sblimit > 20)
466 				{
467 					table_nbal = MpaDecoder.table_b2ab_nbal;
468 					table_alloc = MpaDecoder.table_b2ab;
469 				}
470 				else
471 				{
472 					table_nbal = MpaDecoder.table_b2cd_nbal;
473 					table_alloc = MpaDecoder.table_b2cd;
474 				}
475 			}
476 			else
477 			{
478 				table_nbal = MpaDecoder.table_MPG2_nbal;
479 				table_alloc = MpaDecoder.table_MPG2;
480 			}
481 
482 			for( sb=0; sb<Bound; sb++)
483 			{
484 				for( ch=0; ch<getChannel(); ch++)
485 				{
486 					allocation[sb][ch] = table_alloc[sb][getBits(data, BitPos, table_nbal[sb])];
487 					nr_bits += table_nbal[sb];
488 				}
489 			}
490 
491 			for( sb=Bound; sb<Sblimit; sb++)
492 			{
493 				allocation[sb][0] = allocation[sb][1] = table_alloc[sb][getBits(data, BitPos, table_nbal[sb])];
494 				nr_bits += table_nbal[sb];
495 			}
496 
497 			for( sb=0; sb<Sblimit; sb++)
498 				for( ch=0; ch<getChannel(); ch++)
499 					if (allocation[sb][ch]>0)
500 						nr_bits += 2;
501 		}
502 
503 		int crc = 0xFFFF;
504 
505 		// look up table  is faster
506 		crc = determineCRC(data, offset, nr_bits, crc);
507 
508 		return ((crc != crc_val) ? 1 : 0);
509 	}
510 
511 
512 	/**
513 	 * mpa riff header stuff
514 	 */
515 	private final int[] rpadding = { 0, 1, 1, 4 };
516 	private final int[] rlayer = { 0, 4, 2, 1 };
517 	private final int[][] rsample = {
518 		{ 22050, 24000, 16000, 0 },
519 		{ 44100, 48000, 32000, 0 }
520 	};
521 	private final int[] rmode = { 1, 2, 4, 8 };
522 	private final int[] rchnl = { 2, 2, 2, 1 };
523 	private final int[] rmext = { 1, 2, 4, 8 };
524 	private final int[] remph = { 1, 2, 3, 4 };
525 	private final int[][][] rbitrate = {
526 		{ {  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
527 		{  0,8000,16000,24000,32000,40000,48000,56000,64000,80000,96000,112000,128000,144000,160000,0  },
528 		{  0,8000,16000,24000,32000,40000,48000,56000,64000,80000,96000,112000,128000,144000,160000,0  },
529 		{  0,32000,48000,56000,64000,80000,96000,112000,128000,144000,160000,176000,192000,224000,256000,0 } },
530 		{ {  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
531 		{  0,32000,40000,48000,56000,64000,80000,96000,112000,128000,160000,192000,224000,256000,320000,0  },
532 		{  0,32000,48000,56000,64000,80000,96000,112000,128000,160000,192000,224000,256000,320000,384000,0  },
533 		{  0,32000,64000,96000,128000,160000,192000,224000,256000,288000,320000,352000,384000,416000,448000,0 } }
534 	};
535 
536 
537 	/**
538 	 * riffdata from mpeg audio
539 	 * awaiting a frame byte array, only the header is used
540 	 */
parseRiffData(byte[] rh, int channel)541 	public void parseRiffData(byte[] rh, int channel)
542 	{
543 		int[] riffdata = new int[10];
544 
545 		// fwHeadFlags
546 		riffdata[0] = (8 & rh[1])<<1 | (1 & rh[1])<<3 | (4 & rh[3]) | (8 & rh[3])>>>2 | (1 & rh[2]);
547 		// fwHeadLayer
548 		riffdata[1] = rlayer[(6 & rh[1])>>>1];
549 		// nSamplesPerSec
550 		riffdata[2] = rsample[(8 & rh[1])>>>3][(0xC & rh[2])>>>2];
551 		// fwHeadMode
552 		riffdata[3] = rmode[(0xC0 & rh[3])>>>6];
553 		// nChannels
554 		riffdata[4] = rchnl[(0xC0 & rh[3])>>>6];
555 		// fwHeadModeExt
556 		riffdata[5] = rmext[(0x30 & rh[3])>>>4];
557 		// dwHeadBitrate
558 		riffdata[6] = rbitrate[(8 & rh[1])>>>3][(6 & rh[1])>>>1][(0xF0 & rh[2])>>>4];
559 		// wHeadEmphasis
560 		riffdata[7] = remph[(3 & rh[3])];
561 		// nBlockAlign
562 		riffdata[8] = riffdata[1] == 1 ? 4 * (12 * riffdata[6] / riffdata[2]) :  144 * riffdata[6] / riffdata[2];
563 		riffdata[8] /= ( (8 & rh[1]) == 0 && (6 & rh[1]) == 1 ) ? 2 : 1 ;
564 
565 		if ((2 & rh[2]) != 0)
566 			riffdata[8] += rpadding[(6 & rh[1])>>>1];
567 
568 		setExtraWaveData(riffdata, channel);
569 	}
570 
571 
572 
573 	/**
574 	 * RDS-Test,
575 	 *
576 	 */
577 	ArrayList _list = new ArrayList();
578 	ByteArrayOutputStream bo = new ByteArrayOutputStream();
579 
580 	private boolean DecodeRDS = false;
581 	private boolean Debug = false;
582 	private boolean hasRawData = false;
583 
584 	private final byte RDS_identifier = (byte) 0xFD;
585 	private final int RDS_startcode = 0xFE;
586 	private final int RDS_endcode = 0xFF;
587 
588 	private String[] rds_values = new String[9]; //buffer of messages
589 
590 	private final String[] pty_list = {
591 		"undefined", "News", "Current Affairs", "Information", "Sport", "Education", "Drama", "Culture", "Science",
592 		"Varied", "Pop Music", "Rock Music", "Easy Listening", "Light Classical", "Seriuos Classical", "Other Music",
593 		"Weather", "Finance", "Children", "Social Affairs", "Religion", "Phone In", "Travel", "Leisure", "Jazz Music",
594 		"Country Music", "National Music", "Oldies Music", "Folk Music", "Documentary", "Alarm Test", "Alarm"
595 	};
596 
597 	/**
598 	 * RDS-char map table , unicode
599 	 */
600 	private final short[] chars = {
601 		0x0020, 0x0021, 0x0022, 0x0023, 0x00a4, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
602 		0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
603 		0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
604 		0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
605 		0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
606 		0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0020,
607 		0x00e1, 0x00e0, 0x00e9, 0x00e8, 0x00ed, 0x00ec, 0x00f3, 0x00f2, 0x00fa, 0x00f9, 0x00d1, 0x00c7, 0x015e, 0x00df, 0x0130, 0x0132,
608 		0x00e2, 0x00e4, 0x00ea, 0x00eb, 0x00ee, 0x00ef, 0x00f4, 0x00f6, 0x00fb, 0x00fc, 0x00f1, 0x00e7, 0x015f, 0x011f, 0x0131, 0x0133
609 	};
610 
611 	/**
612 	 *
613 	 */
setAncillaryDataDecoder(boolean b, boolean b1)614 	public void setAncillaryDataDecoder(boolean b, boolean b1)
615 	{
616 		DecodeRDS = b;
617 		Debug = b1;
618 		Arrays.fill(rds_values, null);
619 	}
620 
621 	/**
622 	 *
623 	 */
decodeAncillaryData(byte[] frame, double frametime)624 	public String decodeAncillaryData(byte[] frame, double frametime)
625 	{
626 		if (!DecodeRDS)
627 			return null;
628 
629 		int neg_offs = getSize() - 1;
630 
631 		if (frame[neg_offs] != RDS_identifier)
632 		{
633 	//		neg_offs -= 2;
634 
635 	//		if (frame[neg_offs + 2] != 0 || frame[neg_offs + 1] != 0 || frame[neg_offs] != RDS_identifier)
636 				return null;
637 		}
638 
639 		int len = 0xFF & frame[neg_offs - 1];
640 
641 		for (int i = neg_offs - 2, val; i > 3 && i > neg_offs - 2 - len; i--)
642 		{
643 			val = 0xFF & frame[i];
644 			_list.add(String.valueOf(val));
645 		}
646 
647 		return decodeChunk(_list, frametime);
648 	}
649 
650 	/**
651 	 *
652 	 */
decodeChunk(ArrayList list, double frametime)653 	private String decodeChunk(ArrayList list, double frametime)
654 	{
655 		int index = list.indexOf(String.valueOf(RDS_startcode));
656 
657 		if (index < 0)
658 		{
659 			list.clear();
660 			return null;
661 		}
662 
663 		while (index > 0)
664 		{
665 			list.remove(0);
666 			index--;
667 		}
668 
669 		int eom_index = list.indexOf(String.valueOf(RDS_endcode));
670 
671 		if (eom_index < 0)
672 			return null;
673 
674 		else if (eom_index < 5) //fe xx yy zz ll aa
675 		{
676 			list.remove(0);
677 			return null;
678 		}
679 
680 		if (Debug)
681 		{
682 			String str = "";
683 			String str_1 = "";
684 
685 			for (int i = 0; i <= eom_index; i++)
686 			{
687 				str_1 = Integer.toHexString(Integer.parseInt(list.get(i).toString())).toUpperCase();
688 				str += " " + (str_1.length() < 2 ? "0" + str_1 : str_1);
689 			}
690 
691 			System.out.println("RDS:" + str);
692 		}
693 
694 		int chunk_length = Integer.parseInt(list.get(4).toString());
695 		int real_length = -1;
696 		int type = -1;
697 
698 		// fill bytearray, excluding crc + EOM, correct special bytes
699 		for (int i = 0, j = 0, k = 0, value, identifier_int = (0xFF & RDS_identifier); i <= eom_index; i++, list.remove(0))
700 		{
701 			value = Integer.parseInt(list.get(0).toString());
702 
703 			if (i < 5 || value > identifier_int)
704 				continue;
705 
706 			if (i == 5)
707 			{
708 				type = value;
709 				continue;
710 			}
711 
712 			// coding of 0xFD,FE,FF
713 			if (value == identifier_int)
714 			{
715 				j = 1;
716 				continue;
717 			}
718 
719 			if (j == 1)
720 			{
721 				value += identifier_int;
722 				j = 0;
723 			}
724 
725 			if (k < chunk_length - 1)
726 				bo.write(value);
727 
728 			real_length = k;
729 			k++;
730 		}
731 
732 		// wrong length
733 		if (real_length != chunk_length)
734 			type = -1;
735 
736 		String str = null;
737 
738 		switch (type)
739 		{
740 		case 0xDA: //RASS
741 			getRawData(bo.toByteArray());
742 			break;
743 
744 		case 0x0A: //RT
745 			str = compareMsg(getRT(bo.toByteArray()), 0, frametime);
746 			break;
747 
748 		case 0x01: //PI
749 			str = compareMsg(getPI(bo.toByteArray()), 1, frametime);
750 			break;
751 
752 		case 0x02: //PS program service name
753 			str = compareMsg(getPS(bo.toByteArray()), 2, frametime);
754 			break;
755 
756 		case 0x03: //TA
757 			str = compareMsg(getTP(bo.toByteArray()), 3, frametime);
758 			break;
759 
760 		case 0x05: //MS
761 			str = compareMsg(getMS(bo.toByteArray()), 4, frametime);
762 			break;
763 
764 		case 0x07: //PTY
765 			str = compareMsg(getPTY(bo.toByteArray()), 5, frametime);
766 			break;
767 
768 		case 0x0D: //RTC
769 			str = compareMsg(getRTC(bo.toByteArray()), 6, frametime);
770 			break;
771 
772 		case 0x30: //TMC
773 			str = compareMsg("transmits TMC messages", 7, frametime);
774 			break;
775 
776 		case 0x46: //ODA data
777 			str = compareMsg("transmits ODA messages", 8, frametime);
778 			break;
779 
780 		case 0x40: //ODA SMC
781 		case 0x42: //ODA free
782 		case 0x4A: //CT
783 		case 0x06: //PIN
784 			break;
785 		}
786 
787 		bo.reset();
788 
789 		return str;
790 	}
791 
792 	/**
793 	 *
794 	 */
getRawData(byte[] array)795 	private void getRawData(byte[] array)
796 	{
797 		try {
798 			int index = 0;
799 
800 			int len = 0xFF & array[index];
801 			int end = array.length;
802 
803 			index += 5;
804 
805 			int counter = 0xFF & array[index];
806 
807 			index += 3;
808 
809 			int bound = 0xFF & array[index];
810 
811 			index++;
812 
813 			try {
814 
815 				if (!hasRawData)
816 				{
817 					hasRawData = true;
818 					Common.setMessage("-> exporting RDS data (RASS) to '" + instanced_time + "_RASS@RDS'");
819 				}
820 
821 				BufferedOutputStream rawdata = new BufferedOutputStream(new FileOutputStream(Common.getCollection().getOutputNameParent(instanced_time + "_RASS@RDS"), true));
822 
823 				for (int i = index, k; i < end; i++)
824 				{
825 					k = (0xFF & array[i]);
826 
827 					rawdata.write(k);
828 				}
829 
830 				rawdata.flush();
831 				rawdata.close();
832 
833 			} catch (IOException ie) {
834 				Common.setMessage("!> error rds1");
835 			}
836 
837 		} catch (ArrayIndexOutOfBoundsException ae) {
838 			Common.setMessage("!> error rds2");
839 		}
840 	}
841 
842 	/**
843 	 *
844 	 */
compareMsg(String str, int index, double frametime)845 	private String compareMsg(String str, int index, double frametime)
846 	{
847 		if (str == null || str.equals(rds_values[index]))
848 			return null;
849 
850 		rds_values[index] = str;
851 
852 		return ("-> RDS @ " + Common.formatTime_1((long) (frametime / 90.0)) + ": " + str);
853 	}
854 
855 	/**
856 	 *
857 	 */
getRT(byte[] array)858 	private String getRT(byte[] array)
859 	{
860 		try {
861 			int index = 0;
862 
863 			int dsn = 0xFF & array[index];
864 			int psn = 0xFF & array[index + 1];
865 
866 			index += 2;
867 
868 			int len = 0xFF & array[index];
869 
870 			index++;
871 
872 			int change = 0xFF & array[index];
873 
874 			index++;
875 
876 			String str = getString(array, index, len - 1);
877 
878 			return ("-> RT (" + Integer.toHexString(change).toUpperCase() + "): '" + str.trim() + "'");
879 
880 		} catch (ArrayIndexOutOfBoundsException ae) {}
881 
882 		return null;
883 	}
884 
885 	/**
886 	 *
887 	 */
getPS(byte[] array)888 	private String getPS(byte[] array)
889 	{
890 		try {
891 			int index = 0;
892 
893 			int dsn = 0xFF & array[index];
894 			int psn = 0xFF & array[index + 1];
895 
896 			index += 2;
897 
898 			int len = array.length >= index + 8 ? 8 : array.length - index;
899 
900 			String str = getString(array, index, len);
901 
902 			return ("-> PS (" + psn + "): '" + str.trim() + "'");
903 
904 		} catch (ArrayIndexOutOfBoundsException ae) {}
905 
906 		return null;
907 	}
908 
909 	/**
910 	 *
911 	 */
getPI(byte[] array)912 	private String getPI(byte[] array)
913 	{
914 		try {
915 			int index = 0;
916 
917 			int dsn = 0xFF & array[index];
918 			int psn = 0xFF & array[index + 1];
919 
920 			index += 2;
921 
922 			int pi_code = (0xFF & array[index])<<8 | (0xFF & array[index + 1]);
923 
924 			return ("-> PI (" + psn + "): 0x" + Integer.toHexString(pi_code).toUpperCase());
925 
926 		} catch (ArrayIndexOutOfBoundsException ae) {}
927 
928 		return null;
929 	}
930 
931 	/**
932 	 *
933 	 */
getTP(byte[] array)934 	private String getTP(byte[] array)
935 	{
936 		try {
937 			int index = 0;
938 
939 			int dsn = 0xFF & array[index];
940 			int psn = 0xFF & array[index + 1];
941 
942 			index += 2;
943 
944 			boolean tp = (2 & array[index]) != 0;
945 			boolean ta = (1 & array[index]) != 0;
946 
947 			return ("-> TP/TA (" + psn + "): " + (tp ? "TP" : "no TP") + " / " + (ta ? "TA on air" : "no TA"));
948 
949 		} catch (ArrayIndexOutOfBoundsException ae) {}
950 
951 		return null;
952 	}
953 
954 	/**
955 	 *
956 	 */
getMS(byte[] array)957 	private String getMS(byte[] array)
958 	{
959 		try {
960 			int index = 0;
961 
962 			int dsn = 0xFF & array[index];
963 			int psn = 0xFF & array[index + 1];
964 
965 			index += 2;
966 
967 			boolean speech = (1 & array[index]) != 0;
968 
969 			return ("-> MS (" + psn + "): " + (speech ? "Speech" : "Music"));
970 
971 		} catch (ArrayIndexOutOfBoundsException ae) {}
972 
973 		return null;
974 	}
975 
976 	/**
977 	 *
978 	 */
getPTY(byte[] array)979 	private String getPTY(byte[] array)
980 	{
981 		try {
982 			int index = 0;
983 
984 			int dsn = 0xFF & array[index];
985 			int psn = 0xFF & array[index + 1];
986 
987 			index += 2;
988 
989 			int pty = 0x1F & array[index];
990 
991 			return ("-> PTY (" + psn + "): " + pty_list[pty]);
992 
993 		} catch (ArrayIndexOutOfBoundsException ae) {}
994 
995 		return null;
996 	}
997 
998 	/**
999 	 *
1000 	 */
getRTC(byte[] array)1001 	private String getRTC(byte[] array)
1002 	{
1003 		try {
1004 			int index = 0;
1005 
1006 			String year  = "20" + Common.adaptString(Integer.toHexString(0x7F & array[index]), 2);
1007 			String month = Common.adaptString(String.valueOf(0xF & array[index + 1]), 2);
1008 			String date  = Common.adaptString(String.valueOf(0x1F & array[index + 2]), 2);
1009 			String hour  = Common.adaptString(String.valueOf(0x1F & array[index + 3]), 2);
1010 			String min   = Common.adaptString(String.valueOf(0x3F & array[index + 4]), 2);
1011 			String sec   = Common.adaptString(String.valueOf(0x3F & array[index + 5]), 2);
1012 			String censec= Common.adaptString(String.valueOf(0x7F & array[index + 6]), 2);
1013 
1014 			int ltoffs   = 0xFF & array[index + 7];
1015 
1016 			String loctime = ltoffs != 0xFF ? (((0x20 & ltoffs) != 0) ? "-" + ((0x1F & ltoffs) / 2) : "+" + ((0x1F & ltoffs) / 2)) : "\u00B1" + "0";
1017 
1018 			return ("-> RTC (" + loctime + "h): " + year + "." + month + "." + date + "  " + hour + ":" + min + ":" + sec + "." + censec);
1019 
1020 		} catch (ArrayIndexOutOfBoundsException ae) {}
1021 
1022 		return null;
1023 	}
1024 
1025 	/**
1026 	 *
1027 	 */
getString(byte[] array, int offset, int length)1028 	private String getString(byte[] array, int offset, int length)
1029 	{
1030 		String str = "";
1031 
1032 		try {
1033 
1034 			for (int i = offset, val, j = offset + length; i < j; i++)
1035 			{
1036 				val = 0xFF & array[i];
1037 
1038 				str += (val > 0x9F || val < 0x20) ? (char)chars[0] : (char)chars[val - 0x20];
1039 			}
1040 
1041 		} catch (ArrayIndexOutOfBoundsException ae) {}
1042 
1043 		return str;
1044 	}
1045 
1046 
1047 	/**
1048 	 * part for RIFF wave header data processing
1049 	 */
1050 
1051 	private WaveHeader WaveHeader_Ch1;
1052 	private WaveHeader WaveHeader_Ch2;
1053 
1054 	/**
1055 	 *
1056 	 */
initExtraWaveHeader(boolean bool_ACM, boolean bool_BWF, boolean bool_AC3)1057 	public void initExtraWaveHeader(boolean bool_ACM, boolean bool_BWF, boolean bool_AC3)
1058 	{
1059 		WaveHeader_Ch1 = new WaveHeader(bool_ACM, bool_BWF);
1060 		WaveHeader_Ch2 = new WaveHeader(bool_ACM, bool_BWF);
1061 	}
1062 
1063 	/**
1064 	 *
1065 	 */
getExtraWaveHeader(int channel, boolean placeholder)1066 	public byte[] getExtraWaveHeader(int channel, boolean placeholder)
1067 	{
1068 		switch (channel)
1069 		{
1070 		case 1:
1071 			return (placeholder ? WaveHeader_Ch1.getPlaceHolder() : WaveHeader_Ch1.getHeader());
1072 
1073 		case 2:
1074 			return (placeholder ? WaveHeader_Ch2.getPlaceHolder() : WaveHeader_Ch2.getHeader());
1075 		}
1076 
1077 		return (new byte[0]);
1078 	}
1079 
1080 	/**
1081 	 *
1082 	 */
setExtraWaveData(int[] array, int channel)1083 	public void setExtraWaveData(int[] array, int channel)
1084 	{
1085 		switch (channel)
1086 		{
1087 		case 1:
1088 			WaveHeader_Ch1.setWaveData(array);
1089 			break;
1090 
1091 		case 2:
1092 			WaveHeader_Ch2.setWaveData(array);
1093 			break;
1094 		}
1095 	}
1096 
1097 	/**
1098 	 *
1099 	 */
setExtraWaveLength(long filelength, long timelength, int channel)1100 	public void setExtraWaveLength(long filelength, long timelength, int channel)
1101 	{
1102 		switch (channel)
1103 		{
1104 		case 1:
1105 			WaveHeader_Ch1.setWaveLength(filelength, timelength);
1106 			break;
1107 
1108 		case 2:
1109 			WaveHeader_Ch2.setWaveLength(filelength, timelength);
1110 			break;
1111 		}
1112 	}
1113 
1114 
1115 	/**
1116 	 *
1117 	 */
1118 	private class WaveHeader {
1119 
1120 		private byte[] riffacm = {
1121 			82, 73, 70, 70,  0,  0,  0,  0, 87, 65, 86, 69,102,109,116, 32,
1122 			30,  0,  0,  0, 85,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,
1123 			1,  0,  0,  0, 12,  0,  1,  0,  2,  0,  0,  0,  0,  0,  1,  0,
1124 			113,  5,102, 97, 99,116,  4,  0,  0,  0,  0,  0,  0,  0,100, 97,
1125 			116, 97,  0,  0,  0,  0
1126 		};
1127 
1128 		private byte[] riffbwf = {
1129 			82, 73, 70, 70,  0,  0,  0,  0, 87, 65, 86, 69,102,109,116, 32,
1130 			40,  0,  0,  0, 80,  0,  1,  0,  1,  0,  0,  0,  0,  0,  0,  0,
1131 			0,  0,  0,  0, 22,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,
1132 			0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,102, 97, 99,116,
1133 			4,  0,  0,  0,  0,  0,  0,  0,100, 97,116, 97,  0,  0,  0,  0
1134 		};
1135 
1136 		private long Samples = 0;
1137 		private long SampleCount = 0;
1138 
1139 		private final int HeaderLength_ACM = 70;
1140 		private final int HeaderLength_BWF = 80;
1141 		private final int ACM_WaveFormat = 1;
1142 		private final int BWF_WaveFormat = 2;
1143 
1144 		private int WaveFormat;
1145 
1146 		//init
WaveHeader(boolean bool_ACM, boolean bool_BWF)1147 		public WaveHeader(boolean bool_ACM, boolean bool_BWF)
1148 		{
1149 			WaveFormat = bool_ACM ? ACM_WaveFormat : bool_BWF ? BWF_WaveFormat : 0;
1150 		}
1151 
1152 		/**
1153 		 * get place holder
1154 		 */
getPlaceHolder()1155 		public byte[] getPlaceHolder()
1156 		{
1157 			switch (WaveFormat)
1158 			{
1159 			case ACM_WaveFormat:
1160 				return (new byte[HeaderLength_ACM]);
1161 
1162 			case BWF_WaveFormat:
1163 				return (new byte[HeaderLength_BWF]);
1164 			}
1165 
1166 			return (new byte[0]);
1167 		}
1168 
1169 		/**
1170 		 * get updated header
1171 		 */
getHeader()1172 		public byte[] getHeader()
1173 		{
1174 			switch (WaveFormat)
1175 			{
1176 			case ACM_WaveFormat:
1177 				return riffacm;
1178 
1179 			case BWF_WaveFormat:
1180 				return riffbwf;
1181 			}
1182 
1183 			return (new byte[0]);
1184 		}
1185 
1186 		/**
1187 		 * set wave data
1188 		 */
setWaveData(int[] riffdata)1189 		public void setWaveData(int[] riffdata)
1190 		{
1191 			Samples += riffdata[2];
1192 			SampleCount++;
1193 
1194 			int nSamplesPerSec = getValue(riffbwf, 24, 4, true);
1195 			int dwHeadBitrate  = getValue(riffbwf, 40, 4, true);
1196 			int nBlockAlign    = getValue(riffbwf, 32, 2, true);
1197 
1198 			//nBlockAlign
1199 			if (nBlockAlign == 0)
1200 			{
1201 				setValue(riffacm, 44, 2, true, riffdata[8]);
1202 				setValue(riffbwf, 32, 2, true, riffdata[8]);
1203 			}
1204 
1205 			else if (nBlockAlign != 1 &&  nBlockAlign != riffdata[8])
1206 				setValue(riffbwf, 32, 2, true, 1);
1207 
1208 			//nSamplesPerSec
1209 			if (nSamplesPerSec == 1)
1210 			{
1211 				setValue(riffacm, 24, 4, true, riffdata[2]);
1212 				setValue(riffbwf, 24, 4, true, riffdata[2]);
1213 			}
1214 
1215 			else if (nSamplesPerSec != 0 &&  nSamplesPerSec != riffdata[2])
1216 			{
1217 				setValue(riffacm, 24, 4, true, 0);
1218 				setValue(riffbwf, 24, 4, true, 0);
1219 			}
1220 
1221 			//dwHeadBitrate
1222 			if (dwHeadBitrate == 1)
1223 				setValue(riffbwf, 40, 4, true, riffdata[6]);
1224 
1225 			else if (dwHeadBitrate != 0 &&  dwHeadBitrate != riffdata[6])
1226 				setValue(riffbwf, 40, 4, true, 0);
1227 
1228 			// fwHeadModeExt
1229 			if (riffdata[3] == 2)
1230 				riffbwf[46] |= (byte) riffdata[5];
1231 
1232 			// nChannels
1233 			if (riffbwf[22] == 1)
1234 				riffacm[22] = riffbwf[22] = (byte) riffdata[4];
1235 
1236 			riffbwf[38] |= (byte) riffdata[1];   // fwHeadLayer
1237 			riffbwf[44] |= (byte) riffdata[3];   // fwHeadMode
1238 			riffbwf[48] |= (byte) riffdata[7];   // wHeadEmphasis
1239 			riffbwf[50] |= (byte) riffdata[0];   // fwHeadFlags
1240 		}
1241 
1242 		/**
1243 		 *
1244 		 */
setWaveLength(long filelength, long timelength)1245 		public void setWaveLength(long filelength, long timelength)
1246 		{
1247 			int lengthACM = (int)filelength - HeaderLength_ACM;
1248 			int lengthBWF = (int)filelength - HeaderLength_BWF;
1249 
1250 			for (int i = 0; i < 4; i++)
1251 			{
1252 				riffacm[4 + i] = (byte)(0xFF & (lengthACM + 62)>>>(i * 8));
1253 				riffbwf[4 + i] = (byte)(0xFF & (lengthBWF + 72)>>>(i * 8));
1254 				riffacm[66 + i] = (byte)(0xFF & lengthACM>>>(i * 8));
1255 				riffbwf[76 + i] = (byte)(0xFF & lengthBWF>>>(i * 8));
1256 			}
1257 
1258 			if (filelength <= 100)
1259 				return;
1260 
1261 			int time = (int)timelength;
1262 			int nAvgBytePerSecACM = (int)(1000L * lengthACM / time);
1263 			int nAvgBytePerSecBWF = (int)(1000L * lengthBWF / time);
1264 
1265 			for (int i = 0; i < 4; i++)
1266 			{
1267 				riffacm[28 + i] = (byte)(0xFF & nAvgBytePerSecACM>>>(i * 8));
1268 				riffbwf[28 + i] = (byte)(0xFF & nAvgBytePerSecBWF>>>(i * 8));
1269 			}
1270 
1271 			int fact = (int)(1L * (Samples/SampleCount) * time /1000);
1272 
1273 			for (int i = 0; i < 4; i++)
1274 				riffacm[58 + i] = riffbwf[68 + i] = (byte)(0xFF & fact>>>(i * 8));
1275 		}
1276 	}
1277 
1278 }