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 }