├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── githubci.yml ├── Doxyfile ├── README.md ├── examples ├── DMA_fancy_player │ ├── .due.test.skip │ ├── .esp32.test.skip │ ├── .esp8266.test.skip │ ├── .leonardo.test.skip │ ├── .mega2560.test.skip │ ├── .uno.test.skip │ ├── .zero.test.skip │ └── DMA_fancy_player.ino ├── DMA_play_from_SD │ ├── .due.test.skip │ ├── .esp32.test.skip │ ├── .esp8266.test.skip │ ├── .leonardo.test.skip │ ├── .mega2560.test.skip │ ├── .uno.test.skip │ ├── .zero.test.skip │ └── DMA_play_from_SD.ino ├── DMA_play_from_header │ ├── .due.test.skip │ ├── .esp32.test.skip │ ├── .esp8266.test.skip │ ├── .leonardo.test.skip │ ├── .mega2560.test.skip │ ├── .uno.test.skip │ ├── .zero.test.skip │ ├── DMA_play_from_header.ino │ └── sine.h ├── play_from_QSPI │ └── play_from_QSPI.ino ├── play_from_SD │ ├── .due.test.skip │ ├── .esp32.test.skip │ ├── .esp8266.test.skip │ ├── .leonardo.test.skip │ ├── .mega2560.test.skip │ ├── .uno.test.skip │ ├── .zero.test.skip │ └── play_from_SD.ino ├── play_from_header │ ├── .due.test.skip │ ├── .esp32.test.skip │ ├── .esp8266.test.skip │ ├── .leonardo.test.skip │ ├── .mega2560.test.skip │ ├── .uno.test.skip │ ├── .zero.test.skip │ ├── play_from_header.ino │ └── sine.h ├── standalone │ ├── .gitignore │ ├── Makefile │ └── main.c └── test.mp3 ├── library.properties └── src ├── Adafruit_MP3.cpp ├── Adafruit_MP3.h ├── assembly.h ├── bitstream.c ├── buffers.c ├── coder.h ├── dct32.c ├── dequant.c ├── dqchan.c ├── huffman.c ├── hufftabs.c ├── imdct.c ├── mp3common.h ├── mp3dec.c ├── mp3dec.h ├── mp3tabs.c ├── mpadecobjfixpt.h ├── polyphase.c ├── readme.txt ├── scalfact.c ├── statname.h ├── stproc.c ├── subband.c └── trigtabs.c /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v3 14 | - uses: actions/checkout@v3 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py metro_m4 24 | 25 | # - name: clang 26 | # run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | # - name: doxygen 29 | # env: 30 | # GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | # PRETTYNAME : "Adafruit Native MP3 Library" 32 | # run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit_MP3 [![Build Status](https://github.com/adafruit/Adafruit_MP3/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_MP3/actions) 2 | 3 | This library sets up and performs *native* MP3 audio decoding on various Arduino-compatible platforms including Metro/Feather M4 (SAMD51 chip), teensy 3.6, teensy 3.2, and teensy 3.1. Audio output via the DAC pins. Uses Helix as underlying decoding. On the SAMD51 boards, TC2 is used to create the sample timer (usually 44.1khz or 48khz). Uses a decent chunk of RAM at this time! 4 | 5 | ## UPDATE 6 October 2018 ## 6 | 7 | - Fixed issues with Teensy support - The code `NVIC_DisableIRQ(MP3_IRQn);` applies only to the feather and metro m4 but was applied to all boards which resulted in MP3\_IRQn being undefined. (Adafruit\_MP3.cpp) 8 | - Added support for Teensy 3.5 - Added `defined(__MK64FX512__)` wherever `defined(__MK66FX1M0__)` was found 9 | - Added/modified comments on compiler directives for Teensy boards 10 | - Included test.mp3 sample file (58.3 KB) 11 | - Fix applied to library and the "play_from_SD.ino" example only. *(Other examples may have the same errors so use the above notes to fix other examples if needed.)* 12 | 13 | This release was tested with the Teensy 3.5 only. It is expected that it will work with all other supported boards. *(At least as supported as the previous version.)* 14 | 15 | ### Some notes regarding audio file format ### 16 | 17 | The tutorial posted on [https://learn.adafruit.com/native-mp3-decoding-on-arduino](https://learn.adafruit.com/native-mp3-decoding-on-arduino "https://learn.adafruit.com/native-mp3-decoding-on-arduino") states: 18 | > This function is called from an interrupt, so it should be short and sweet. It's getting called 44,100 to 48,000 times per second for most MP3 files. 19 | 20 | This means that the MP3 files should be encoded within this range. The code is written for stereo MP3 files so if you have a mono MP3 file, it will not play back using this code as is. 21 | 22 | Best practice for producing playable MP3 files 23 | 24 | - Encode at constant 40kbps with a sample rate of 44,100 kHz 25 | - Stereo only 26 | 27 | Resources for encoding audio 28 | 29 | - Online converter to strip audio from video or convert audio to MP3 or change bitrate - [https://online-audio-converter.com/](https://online-audio-converter.com/ "https://online-audio-converter.com/") 30 | - Desktop software for conversion - [https://www.audacityteam.org/](https://www.audacityteam.org/ "Audacity") 31 | - How to use Audacity to convert mono to stereo - [https://www.wikihow.com/Change-a-Mono-Track-Into-Stereo-Track-Using-Audacity](https://www.wikihow.com/Change-a-Mono-Track-Into-Stereo-Track-Using-Audacity) 32 | 33 | Other notes 34 | 35 | 36 | 37 | - SD Cards (at least on Teensy 3.5 & 3.6 need to be formatted with FAT32 file system. If a small card is used with FAT formatting, it will not work. 38 | - If you receive errors with Teensy 3.5 & 3.6 code regarding the parameters for SD card initialization, look for warnings regarding the SD library. Most likely you have multiple libraries installed and the Teensy SD library is being skipped/ignored. If this is the case, you will need to move or remove the one being used, at least temporarily, so that the Teensy library is used by the Arduino IDE. 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /examples/DMA_fancy_player/.due.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_fancy_player/.due.test.skip -------------------------------------------------------------------------------- /examples/DMA_fancy_player/.esp32.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_fancy_player/.esp32.test.skip -------------------------------------------------------------------------------- /examples/DMA_fancy_player/.esp8266.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_fancy_player/.esp8266.test.skip -------------------------------------------------------------------------------- /examples/DMA_fancy_player/.leonardo.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_fancy_player/.leonardo.test.skip -------------------------------------------------------------------------------- /examples/DMA_fancy_player/.mega2560.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_fancy_player/.mega2560.test.skip -------------------------------------------------------------------------------- /examples/DMA_fancy_player/.uno.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_fancy_player/.uno.test.skip -------------------------------------------------------------------------------- /examples/DMA_fancy_player/.zero.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_fancy_player/.zero.test.skip -------------------------------------------------------------------------------- /examples/DMA_fancy_player/DMA_fancy_player.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * A fancy DMA MP3 player 3 | * the PLAY pin will start playback from the beginning of the file 4 | * the PAUSE pin will pause playback at the current point 5 | * the RESUME pin will resume playback at the point it was paused 6 | * a potentiometer is connected to the VOLUME pin to set the playback volume 7 | */ 8 | 9 | #include "Adafruit_MP3.h" 10 | #include 11 | #include 12 | 13 | #include 14 | #include "utility/dma.h" 15 | 16 | #define VOLUME_MAX 2047 17 | #define PIN_PAUSE 5 18 | #define PIN_RESUME 6 19 | #define PIN_PLAY 9 20 | #define PIN_VOLUME A3 21 | 22 | const char *filename = "test3.mp3"; 23 | const int chipSelect = 10; 24 | 25 | Adafruit_ZeroDMA leftDMA; 26 | Adafruit_ZeroDMA rightDMA; 27 | ZeroDMAstatus stat; // DMA status codes returned by some functions 28 | File dataFile; 29 | Adafruit_MP3_DMA player; 30 | DmacDescriptor *desc; 31 | 32 | //the output data buffers 33 | int16_t *ping, *pong; 34 | int volume; 35 | 36 | //this gets called when the player wants more data 37 | int getMoreData(uint8_t *writeHere, int thisManyBytes){ 38 | int bytesRead = 0; 39 | while(dataFile.available() && bytesRead < thisManyBytes){ 40 | *writeHere = dataFile.read(); 41 | writeHere++; 42 | bytesRead++; 43 | } 44 | return bytesRead; 45 | } 46 | 47 | 48 | //this will get called when data has been decoded 49 | void decodeCallback(int16_t *data, int len){ 50 | for(int i=0; iDATA[0]), // to here (M4) 85 | MP3_OUTBUF_SIZE, 86 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 87 | true, // increment source addr? 88 | false); 89 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 90 | 91 | desc = leftDMA.addDescriptor( 92 | pong, // move data from here 93 | (void *)(&DAC->DATA[0]), // to here (M4) 94 | MP3_OUTBUF_SIZE, 95 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 96 | true, // increment source addr? 97 | false); // increment dest addr? 98 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 99 | 100 | //make the descriptor list loop 101 | leftDMA.loop(true); 102 | leftDMA.setCallback(dma_callback); 103 | 104 | rightDMA.setTrigger(MP3_DMA_TRIGGER); 105 | rightDMA.setAction(DMA_TRIGGER_ACTON_BEAT); 106 | stat = rightDMA.allocate(); 107 | 108 | //make the descriptors 109 | desc = rightDMA.addDescriptor( 110 | ping + 1, // move data from here 111 | (void *)(&DAC->DATA[1]), // to here (M4) 112 | MP3_OUTBUF_SIZE, // this many... 113 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 114 | true, // increment source addr? 115 | false); // increment dest addr? 116 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 117 | 118 | desc = rightDMA.addDescriptor( 119 | pong + 1, // move data from here 120 | (void *)(&DAC->DATA[1]), // to here (M4) 121 | MP3_OUTBUF_SIZE, // this many... 122 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 123 | true, // increment source addr? 124 | false); // increment dest addr? 125 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 126 | 127 | //make the descriptor list loop 128 | rightDMA.loop(true); 129 | rightDMA.setCallback(doNothing); 130 | } 131 | 132 | void initStereoDMA(){ 133 | //######### LEFT CHANNEL DMA ##############// 134 | 135 | //set up the DMA channels 136 | leftDMA.setTrigger(MP3_DMA_TRIGGER); 137 | leftDMA.setAction(DMA_TRIGGER_ACTON_BEAT); 138 | stat = leftDMA.allocate(); 139 | 140 | //ask for the buffers we're going to use 141 | player.getBuffers(&ping, &pong); 142 | 143 | //make the descriptors 144 | desc = leftDMA.addDescriptor( 145 | ping, // move data from here 146 | (void *)(&DAC->DATA[0]), // to here (M4) 147 | MP3_OUTBUF_SIZE >> 1, // this many... 148 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 149 | true, // increment source addr? 150 | false, 151 | DMA_ADDRESS_INCREMENT_STEP_SIZE_2, 152 | DMA_STEPSEL_SRC); // increment dest addr? 153 | 154 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 155 | 156 | desc = leftDMA.addDescriptor( 157 | pong, // move data from here 158 | (void *)(&DAC->DATA[0]), // to here (M4) 159 | MP3_OUTBUF_SIZE >> 1, // this many... 160 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 161 | true, // increment source addr? 162 | false, 163 | DMA_ADDRESS_INCREMENT_STEP_SIZE_2, 164 | DMA_STEPSEL_SRC); // increment dest addr? 165 | 166 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 167 | 168 | //make the descriptor list loop 169 | leftDMA.loop(true); 170 | leftDMA.setCallback(dma_callback); 171 | 172 | //######### RIGHT CHANNEL DMA ##############// 173 | 174 | rightDMA.setTrigger(MP3_DMA_TRIGGER); 175 | rightDMA.setAction(DMA_TRIGGER_ACTON_BEAT); 176 | stat = rightDMA.allocate(); 177 | 178 | //make the descriptors 179 | desc = rightDMA.addDescriptor( 180 | ping + 1, // move data from here 181 | (void *)(&DAC->DATA[1]), // to here (M4) 182 | MP3_OUTBUF_SIZE >> 1, // this many... 183 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 184 | true, // increment source addr? 185 | false, 186 | DMA_ADDRESS_INCREMENT_STEP_SIZE_2, 187 | DMA_STEPSEL_SRC); // increment dest addr? 188 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 189 | 190 | desc = rightDMA.addDescriptor( 191 | pong + 1, // move data from here 192 | (void *)(&DAC->DATA[1]), // to here (M4) 193 | MP3_OUTBUF_SIZE >> 1, // this many... 194 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 195 | true, // increment source addr? 196 | false, 197 | DMA_ADDRESS_INCREMENT_STEP_SIZE_2, 198 | DMA_STEPSEL_SRC); // increment dest addr? 199 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 200 | 201 | //make the descriptor list loop 202 | rightDMA.loop(true); 203 | rightDMA.setCallback(doNothing); 204 | } 205 | 206 | // the setup routine runs once when you press reset: 207 | void setup() { 208 | pinMode(13, OUTPUT); 209 | Serial.begin(9600); 210 | while(!Serial); 211 | 212 | pinMode(PIN_PAUSE, INPUT_PULLUP); 213 | pinMode(PIN_RESUME, INPUT_PULLUP); 214 | pinMode(PIN_PLAY, INPUT_PULLUP); 215 | 216 | while (!SD.begin(12000000, chipSelect)) { 217 | Serial.println("Card failed, or not present"); 218 | delay(2000); 219 | } 220 | Serial.println("card initialized."); 221 | 222 | dataFile = SD.open(filename); 223 | if(!dataFile){ 224 | Serial.println("could not open file!"); 225 | while(1); 226 | } 227 | 228 | //set the DAC to the center of the range 229 | analogWrite(A0, 2048); 230 | analogWrite(A1, 2048); 231 | 232 | //begin the player 233 | player.begin(); 234 | 235 | //this will be how the player asks for data 236 | player.setBufferCallback(getMoreData); 237 | 238 | //this will be how the player asks you to clean the data 239 | player.setDecodeCallback(decodeCallback); 240 | } 241 | 242 | void loop() { 243 | //read volume control 244 | int v = analogRead(PIN_VOLUME); 245 | volume = map(v, 0, 1023, 0, VOLUME_MAX); 246 | 247 | //read pins 248 | 249 | if(!digitalRead(PIN_PAUSE)){ 250 | player.pause(); 251 | } 252 | else if(!digitalRead(PIN_RESUME)){ 253 | player.resume(); 254 | } 255 | else if(!digitalRead(PIN_PLAY)){ 256 | //this button will restart playback of the file 257 | rightDMA.abort(); 258 | leftDMA.abort(); 259 | 260 | if(dataFile){ 261 | dataFile.close(); 262 | } 263 | dataFile = SD.open(filename); 264 | if(!dataFile){ 265 | Serial.println("could not open file!"); 266 | while(1); 267 | } 268 | 269 | player.play(); //this will automatically fill the first buffer and get the channel info 270 | 271 | if(player.numChannels == 1) 272 | initMonoDMA(); //this is a mono file 273 | 274 | else if(player.numChannels == 2) 275 | initStereoDMA(); //this is a stereo file 276 | 277 | else{ 278 | Serial.println("only mono and stereo files are supported"); 279 | while(1); 280 | } 281 | 282 | rightDMA.startJob(); 283 | leftDMA.startJob(); 284 | } 285 | delay(20); 286 | } 287 | 288 | -------------------------------------------------------------------------------- /examples/DMA_play_from_SD/.due.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_SD/.due.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_SD/.esp32.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_SD/.esp32.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_SD/.esp8266.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_SD/.esp8266.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_SD/.leonardo.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_SD/.leonardo.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_SD/.mega2560.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_SD/.mega2560.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_SD/.uno.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_SD/.uno.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_SD/.zero.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_SD/.zero.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_SD/DMA_play_from_SD.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Play an MP3 file from an SD card 3 | */ 4 | #include "Adafruit_MP3.h" 5 | #include 6 | #include 7 | 8 | #include 9 | #include "utility/dma.h" 10 | 11 | #define VOLUME_MAX 2047 12 | const char *filename = "test3.mp3"; 13 | const int chipSelect = 10; 14 | 15 | Adafruit_ZeroDMA leftDMA; 16 | Adafruit_ZeroDMA rightDMA; 17 | ZeroDMAstatus stat; // DMA status codes returned by some functions 18 | File dataFile; 19 | Adafruit_MP3_DMA player; 20 | DmacDescriptor *desc; 21 | 22 | //the output data buffers 23 | int16_t *ping, *pong; 24 | 25 | //this gets called when the player wants more data 26 | int getMoreData(uint8_t *writeHere, int thisManyBytes){ 27 | int bytesRead = 0; 28 | while(dataFile.available() && bytesRead < thisManyBytes){ 29 | *writeHere = dataFile.read(); 30 | writeHere++; 31 | bytesRead++; 32 | } 33 | return bytesRead; 34 | } 35 | 36 | 37 | //this will get called when data has been decoded 38 | void decodeCallback(int16_t *data, int len){ 39 | for(int i=0; iDATA[0]), // to here (M4) 74 | MP3_OUTBUF_SIZE, 75 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 76 | true, // increment source addr? 77 | false); 78 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 79 | 80 | desc = leftDMA.addDescriptor( 81 | pong, // move data from here 82 | (void *)(&DAC->DATA[0]), // to here (M4) 83 | MP3_OUTBUF_SIZE, 84 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 85 | true, // increment source addr? 86 | false); // increment dest addr? 87 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 88 | 89 | //make the descriptor list loop 90 | leftDMA.loop(true); 91 | leftDMA.setCallback(dma_callback); 92 | 93 | rightDMA.setTrigger(MP3_DMA_TRIGGER); 94 | rightDMA.setAction(DMA_TRIGGER_ACTON_BEAT); 95 | stat = rightDMA.allocate(); 96 | 97 | //make the descriptors 98 | desc = rightDMA.addDescriptor( 99 | ping + 1, // move data from here 100 | (void *)(&DAC->DATA[1]), // to here (M4) 101 | MP3_OUTBUF_SIZE, // this many... 102 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 103 | true, // increment source addr? 104 | false); // increment dest addr? 105 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 106 | 107 | desc = rightDMA.addDescriptor( 108 | pong + 1, // move data from here 109 | (void *)(&DAC->DATA[1]), // to here (M4) 110 | MP3_OUTBUF_SIZE, // this many... 111 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 112 | true, // increment source addr? 113 | false); // increment dest addr? 114 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 115 | 116 | //make the descriptor list loop 117 | rightDMA.loop(true); 118 | rightDMA.setCallback(doNothing); 119 | } 120 | 121 | void initStereoDMA(){ 122 | //######### LEFT CHANNEL DMA ##############// 123 | 124 | //set up the DMA channels 125 | leftDMA.setTrigger(MP3_DMA_TRIGGER); 126 | leftDMA.setAction(DMA_TRIGGER_ACTON_BEAT); 127 | stat = leftDMA.allocate(); 128 | 129 | //ask for the buffers we're going to use 130 | player.getBuffers(&ping, &pong); 131 | 132 | //make the descriptors 133 | desc = leftDMA.addDescriptor( 134 | ping, // move data from here 135 | (void *)(&DAC->DATA[0]), // to here (M4) 136 | MP3_OUTBUF_SIZE >> 1, // this many... 137 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 138 | true, // increment source addr? 139 | false, 140 | DMA_ADDRESS_INCREMENT_STEP_SIZE_2, 141 | DMA_STEPSEL_SRC); // increment dest addr? 142 | 143 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 144 | 145 | desc = leftDMA.addDescriptor( 146 | pong, // move data from here 147 | (void *)(&DAC->DATA[0]), // to here (M4) 148 | MP3_OUTBUF_SIZE >> 1, // this many... 149 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 150 | true, // increment source addr? 151 | false, 152 | DMA_ADDRESS_INCREMENT_STEP_SIZE_2, 153 | DMA_STEPSEL_SRC); // increment dest addr? 154 | 155 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 156 | 157 | //make the descriptor list loop 158 | leftDMA.loop(true); 159 | leftDMA.setCallback(dma_callback); 160 | 161 | //######### RIGHT CHANNEL DMA ##############// 162 | 163 | rightDMA.setTrigger(MP3_DMA_TRIGGER); 164 | rightDMA.setAction(DMA_TRIGGER_ACTON_BEAT); 165 | stat = rightDMA.allocate(); 166 | 167 | //make the descriptors 168 | desc = rightDMA.addDescriptor( 169 | ping + 1, // move data from here 170 | (void *)(&DAC->DATA[1]), // to here (M4) 171 | MP3_OUTBUF_SIZE >> 1, // this many... 172 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 173 | true, // increment source addr? 174 | false, 175 | DMA_ADDRESS_INCREMENT_STEP_SIZE_2, 176 | DMA_STEPSEL_SRC); // increment dest addr? 177 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 178 | 179 | desc = rightDMA.addDescriptor( 180 | pong + 1, // move data from here 181 | (void *)(&DAC->DATA[1]), // to here (M4) 182 | MP3_OUTBUF_SIZE >> 1, // this many... 183 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 184 | true, // increment source addr? 185 | false, 186 | DMA_ADDRESS_INCREMENT_STEP_SIZE_2, 187 | DMA_STEPSEL_SRC); // increment dest addr? 188 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 189 | 190 | //make the descriptor list loop 191 | rightDMA.loop(true); 192 | rightDMA.setCallback(doNothing); 193 | } 194 | 195 | // the setup routine runs once when you press reset: 196 | void setup() { 197 | pinMode(13, OUTPUT); 198 | Serial.begin(9600); 199 | while(!Serial); 200 | 201 | 202 | while (!SD.begin(12000000, chipSelect)) { 203 | Serial.println("Card failed, or not present"); 204 | delay(2000); 205 | } 206 | Serial.println("card initialized."); 207 | 208 | dataFile = SD.open(filename); 209 | if(!dataFile){ 210 | Serial.println("could not open file!"); 211 | while(1); 212 | } 213 | 214 | //set the DAC to the center of the range 215 | analogWrite(A0, 2048); 216 | analogWrite(A1, 2048); 217 | 218 | //begin the player 219 | player.begin(); 220 | 221 | //this will be how the player asks for data 222 | player.setBufferCallback(getMoreData); 223 | 224 | //this will be how the player asks you to clean the data 225 | player.setDecodeCallback(decodeCallback); 226 | 227 | player.play(); //this will automatically fill the first buffer and get the channel info 228 | 229 | if(player.numChannels == 1) 230 | initMonoDMA(); //this is a mono file 231 | 232 | else if(player.numChannels == 2) 233 | initStereoDMA(); //this is a stereo file 234 | 235 | else{ 236 | Serial.println("only mono and stereo files are supported"); 237 | while(1); 238 | } 239 | 240 | //the DMA controller will dictate what happens from here on out 241 | rightDMA.startJob(); 242 | leftDMA.startJob(); 243 | } 244 | 245 | // the loop routine runs over and over again forever: 246 | void loop() { 247 | //do nothing 248 | } 249 | -------------------------------------------------------------------------------- /examples/DMA_play_from_header/.due.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_header/.due.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_header/.esp32.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_header/.esp32.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_header/.esp8266.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_header/.esp8266.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_header/.leonardo.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_header/.leonardo.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_header/.mega2560.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_header/.mega2560.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_header/.uno.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_header/.uno.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_header/.zero.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/DMA_play_from_header/.zero.test.skip -------------------------------------------------------------------------------- /examples/DMA_play_from_header/DMA_play_from_header.ino: -------------------------------------------------------------------------------- 1 | #include "Adafruit_MP3.h" 2 | #include "sine.h" 3 | 4 | #include 5 | #include "utility/dma.h" 6 | 7 | #define VOLUME_MAX 2047 8 | 9 | Adafruit_ZeroDMA myDMA; 10 | ZeroDMAstatus stat; // DMA status codes returned by some functions 11 | Adafruit_MP3_DMA player; 12 | DmacDescriptor *desc; 13 | 14 | //the output data buffers 15 | int16_t *ping, *pong; 16 | 17 | uint8_t *currentPtr; 18 | uint32_t thisManyBytesLeft; 19 | 20 | //this gets called when the player wants more data 21 | int getMoreData(uint8_t *writeHere, int thisManyBytes){ 22 | int toWrite = min(thisManyBytesLeft, thisManyBytes); 23 | memcpy(writeHere, currentPtr, toWrite); 24 | currentPtr += toWrite; 25 | thisManyBytesLeft -= toWrite; 26 | return toWrite; 27 | } 28 | 29 | 30 | //this will get called when data has been decoded 31 | void decodeCallback(int16_t *data, int len){ 32 | for(int i=0; iDATA[0]), // to here (M4) 63 | MP3_OUTBUF_SIZE, // this many... 64 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 65 | true, // increment source addr? 66 | false); // increment dest addr? 67 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 68 | 69 | desc = myDMA.addDescriptor( 70 | pong, // move data from here 71 | (void *)(&DAC->DATA[0]), // to here (M4) 72 | MP3_OUTBUF_SIZE, // this many... 73 | DMA_BEAT_SIZE_HWORD, // bytes/hword/words 74 | true, // increment source addr? 75 | false); // increment dest addr? 76 | desc->BTCTRL.bit.BLOCKACT = DMA_BLOCK_ACTION_INT; 77 | 78 | //make the descriptor list loop 79 | myDMA.loop(true); 80 | myDMA.setCallback(dma_callback); 81 | 82 | //set the DAC to the center of the range 83 | analogWrite(A0, 2048); 84 | 85 | currentPtr = (uint8_t*)sine_mp3; 86 | thisManyBytesLeft = sizeof(sine_mp3); 87 | 88 | //begin the player 89 | player.begin(); 90 | 91 | //this will be how the player asks for data 92 | player.setBufferCallback(getMoreData); 93 | 94 | //this will be how the player asks you to clean the data 95 | player.setDecodeCallback(decodeCallback); 96 | 97 | player.play(); //this will automatically fill the first buffer 98 | 99 | //the DMA controller will dictate what happens from here on out 100 | myDMA.startJob(); 101 | } 102 | 103 | // the loop routine runs over and over again forever: 104 | void loop() { 105 | 106 | } 107 | -------------------------------------------------------------------------------- /examples/play_from_QSPI/play_from_QSPI.ino: -------------------------------------------------------------------------------- 1 | #include "Adafruit_MP3.h" 2 | #include 3 | #include 4 | #include 5 | 6 | #if defined(__SAMD51__) || defined(NRF52840_XXAA) 7 | Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3); 8 | #else 9 | #if (SPI_INTERFACES_COUNT == 1 || defined(ADAFRUIT_CIRCUITPLAYGROUND_M0)) 10 | Adafruit_FlashTransport_SPI flashTransport(SS, &SPI); 11 | #else 12 | Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1); 13 | #endif 14 | #endif 15 | 16 | Adafruit_SPIFlash flash(&flashTransport); 17 | 18 | // file system object from SdFat 19 | FatFileSystem fatfs; 20 | 21 | //set this to a value between 0 and 4095 to raise/lower volume 22 | #define VOLUME_MAX 1023 23 | 24 | const char *filename = "test.mp3"; 25 | 26 | File dataFile; 27 | Adafruit_MP3 player; 28 | 29 | void writeDacs(int16_t l, int16_t r){ 30 | uint16_t vall = map(l, -32768, 32767, 0, VOLUME_MAX); 31 | uint16_t valr = map(r, -32768, 32767, 0, VOLUME_MAX); 32 | #if defined(__SAMD51__) // feather/metro m4 33 | analogWrite(A0, vall); 34 | analogWrite(A1, valr); 35 | #elif defined(__MK66FX1M0__) // teensy 3.6 36 | analogWrite(A21, vall); 37 | analogWrite(A22, valr); 38 | #elif defined(NRF52) 39 | analogWrite(27, vall); 40 | #elif defined(__MK20DX256__) //teensy 3.2 41 | analogWrite(A14, vall); //this board only has one dac, so play only left channel (or mono) 42 | #endif 43 | } 44 | 45 | int getMoreData(uint8_t *writeHere, int thisManyBytes){ 46 | int bytesRead = 0; 47 | int toRead = min(thisManyBytes, 768); //limit the number of bytes we can read at a time so the file isn't interrupted 48 | while(dataFile.available() && bytesRead < toRead){ 49 | *writeHere = dataFile.read(); 50 | writeHere++; 51 | bytesRead++; 52 | } 53 | return bytesRead; 54 | } 55 | 56 | // the setup routine runs once when you press reset: 57 | void setup() { 58 | 59 | // Open serial communications and wait for port to open: 60 | Serial.begin(9600); 61 | while (!Serial) { 62 | ; // wait for serial port to connect. Needed for native USB port only 63 | } 64 | 65 | analogWriteResolution(12); 66 | #if defined(__SAMD51__) 67 | analogWrite(A0, 2048); 68 | analogWrite(A1, 2048); 69 | #endif 70 | 71 | Serial.println("Native MP3 decoding!"); 72 | Serial.print("Initializing QSPI storage..."); 73 | 74 | // Initialize flash library and check its chip ID. 75 | if (!flash.begin()) { 76 | Serial.println("Error, failed to initialize flash chip!"); 77 | while(1); 78 | } 79 | 80 | Serial.println("QSPI initialized."); 81 | Serial.print("Flash chip JEDEC ID: 0x"); Serial.println(flash.getJEDECID(), HEX); 82 | 83 | // First call begin to mount the filesystem. Check that it returns true 84 | // to make sure the filesystem was mounted. 85 | if (!fatfs.begin(&flash)) { 86 | Serial.println("Error, failed to mount newly formatted filesystem!"); 87 | Serial.println("Was the flash chip formatted with the fatfs_format example?"); 88 | while(1); 89 | } 90 | Serial.println("Mounted filesystem!"); 91 | 92 | 93 | dataFile = fatfs.open(filename); 94 | if(!dataFile){ 95 | Serial.println("could not open file!"); 96 | while(1); 97 | } 98 | 99 | player.begin(); 100 | 101 | //do this when there are samples ready 102 | player.setSampleReadyCallback(writeDacs); 103 | 104 | //do this when more data is required 105 | player.setBufferCallback(getMoreData); 106 | 107 | player.play(); 108 | } 109 | 110 | // the loop routine runs over and over again forever: 111 | void loop() { 112 | player.tick(); 113 | } -------------------------------------------------------------------------------- /examples/play_from_SD/.due.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_SD/.due.test.skip -------------------------------------------------------------------------------- /examples/play_from_SD/.esp32.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_SD/.esp32.test.skip -------------------------------------------------------------------------------- /examples/play_from_SD/.esp8266.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_SD/.esp8266.test.skip -------------------------------------------------------------------------------- /examples/play_from_SD/.leonardo.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_SD/.leonardo.test.skip -------------------------------------------------------------------------------- /examples/play_from_SD/.mega2560.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_SD/.mega2560.test.skip -------------------------------------------------------------------------------- /examples/play_from_SD/.uno.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_SD/.uno.test.skip -------------------------------------------------------------------------------- /examples/play_from_SD/.zero.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_SD/.zero.test.skip -------------------------------------------------------------------------------- /examples/play_from_SD/play_from_SD.ino: -------------------------------------------------------------------------------- 1 | #include "Adafruit_MP3.h" 2 | #include 3 | #include 4 | 5 | //set this to a value between 0 and 4095 to raise/lower volume 6 | #define VOLUME_MAX 1023 7 | 8 | #if defined(__MK66FX1M0__) || defined(__MK64FX512__) // teensy 3.6 or 3.5 9 | const int chipSelect = BUILTIN_SDCARD ; 10 | #elif defined(__MK20DX256__) //teensy 3.1 11 | const int chipSelect = 10; 12 | #else 13 | const int chipSelect = 11; 14 | #endif 15 | const char *filename = "test.mp3"; 16 | 17 | File dataFile; 18 | Adafruit_MP3 player; 19 | 20 | void writeDacs(int16_t l, int16_t r){ 21 | uint16_t vall = map(l, -32768, 32767, 0, VOLUME_MAX); 22 | uint16_t valr = map(r, -32768, 32767, 0, VOLUME_MAX); 23 | #if defined(__SAMD51__) // feather/metro m4 24 | analogWrite(A0, vall); 25 | analogWrite(A1, valr); 26 | #elif defined(__MK66FX1M0__) || defined(__MK64FX512__) // teensy 3.6 or 3.5 27 | analogWrite(A21, vall); 28 | analogWrite(A22, valr); 29 | #elif defined(NRF52) 30 | analogWrite(27, vall); 31 | #elif defined(__MK20DX256__) //teensy 3.2 32 | analogWrite(A14, vall); //this board only has one dac, so play only left channel (or mono) 33 | #endif 34 | } 35 | 36 | int getMoreData(uint8_t *writeHere, int thisManyBytes){ 37 | int bytesRead = 0; 38 | int toRead = min(thisManyBytes, 768); //limit the number of bytes we can read at a time so the file isn't interrupted 39 | while(dataFile.available() && bytesRead < toRead){ 40 | *writeHere = dataFile.read(); 41 | writeHere++; 42 | bytesRead++; 43 | } 44 | return bytesRead; 45 | } 46 | 47 | // the setup routine runs once when you press reset: 48 | void setup() { 49 | 50 | // Open serial communications and wait for port to open: 51 | Serial.begin(9600); 52 | while (!Serial) { 53 | ; // wait for serial port to connect. Needed for native USB port only 54 | } 55 | 56 | Serial.println("Native MP3 decoding!"); 57 | Serial.print("Initializing SD card..."); 58 | 59 | // see if the card is present and can be initialized: 60 | #if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__) // teensy 3.6, 3.5, or 3.1/2 61 | analogWriteResolution(12); 62 | while (!SD.begin(chipSelect)) { 63 | #else 64 | while (!SD.begin(12000000, chipSelect)) { 65 | #endif 66 | Serial.println("Card failed, or not present"); 67 | delay(2000); 68 | } 69 | Serial.println("card initialized."); 70 | 71 | dataFile = SD.open(filename); 72 | if(!dataFile){ 73 | Serial.println("could not open file!"); 74 | while(1); 75 | } 76 | 77 | player.begin(); 78 | 79 | //do this when there are samples ready 80 | player.setSampleReadyCallback(writeDacs); 81 | 82 | //do this when more data is required 83 | player.setBufferCallback(getMoreData); 84 | 85 | player.play(); 86 | } 87 | 88 | // the loop routine runs over and over again forever: 89 | void loop() { 90 | player.tick(); 91 | } -------------------------------------------------------------------------------- /examples/play_from_header/.due.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_header/.due.test.skip -------------------------------------------------------------------------------- /examples/play_from_header/.esp32.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_header/.esp32.test.skip -------------------------------------------------------------------------------- /examples/play_from_header/.esp8266.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_header/.esp8266.test.skip -------------------------------------------------------------------------------- /examples/play_from_header/.leonardo.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_header/.leonardo.test.skip -------------------------------------------------------------------------------- /examples/play_from_header/.mega2560.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_header/.mega2560.test.skip -------------------------------------------------------------------------------- /examples/play_from_header/.uno.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_header/.uno.test.skip -------------------------------------------------------------------------------- /examples/play_from_header/.zero.test.skip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/examples/play_from_header/.zero.test.skip -------------------------------------------------------------------------------- /examples/play_from_header/play_from_header.ino: -------------------------------------------------------------------------------- 1 | #include "Adafruit_MP3.h" 2 | #include "sine.h" 3 | 4 | Adafruit_MP3 player; 5 | 6 | void writeDacs(int16_t l, int16_t r){ 7 | uint16_t val = map(l, -32768, 32767, 0, 4095); 8 | #if defined(__SAMD51__) // feather/metro m4 9 | analogWrite(A0, val); 10 | #elif defined(__MK66FX1M0__) || defined(__MK20DX256__) // teensy 3.6 11 | analogWrite(A21, val); 12 | #endif 13 | } 14 | 15 | uint8_t *currentPtr; 16 | uint32_t thisManyBytesLeft; 17 | 18 | int getMoreData(uint8_t *writeHere, int thisManyBytes){ 19 | int toWrite = min(thisManyBytesLeft, thisManyBytes); 20 | memcpy(writeHere, currentPtr, toWrite); 21 | currentPtr += toWrite; 22 | thisManyBytesLeft -= toWrite; 23 | return toWrite; 24 | } 25 | 26 | // the setup routine runs once when you press reset: 27 | void setup() { 28 | 29 | #if defined(__SAMD51__) 30 | //set the DAC to the center of the range 31 | analogWrite(A0, 2048); 32 | #endif 33 | 34 | currentPtr = (uint8_t*)sine_mp3; 35 | thisManyBytesLeft = sizeof(sine_mp3); 36 | 37 | player.begin(); 38 | 39 | //do this when there are samples ready 40 | player.setSampleReadyCallback(writeDacs); 41 | 42 | //do this when more data is required 43 | player.setBufferCallback(getMoreData); 44 | 45 | player.play(); 46 | } 47 | 48 | // the loop routine runs over and over again forever: 49 | void loop() { 50 | player.tick(); 51 | } -------------------------------------------------------------------------------- /examples/standalone/.gitignore: -------------------------------------------------------------------------------- 1 | decoder 2 | decoder.exe 3 | -------------------------------------------------------------------------------- /examples/standalone/Makefile: -------------------------------------------------------------------------------- 1 | decoder: $(wildcard ../../src/*.c) main.c $(wildcard ../../src/*.h) Makefile 2 | gcc -Og -ggdb -g3 -iquote ../../src -o $@ $(filter %.c, $^) \ 3 | -D'MPDEC_ALLOCATOR(x)=(calloc((x),1))' -DMPDEC_FREE=free -include stdlib.h \ 4 | -fwrapv -Wall 5 | .PHONY: clean 6 | clean: 7 | rm -f decoder 8 | -------------------------------------------------------------------------------- /examples/standalone/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "mp3dec.h" 8 | 9 | #define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN) 10 | 11 | int16_t audiodata[MAX_BUFFER_LEN]; 12 | 13 | typedef struct { 14 | char *ptr, *end; 15 | } stream; 16 | #define READ_PTR(stream) ((void*)((stream)->ptr)) 17 | #define BYTES_LEFT(stream) ((stream)->end - (stream)->ptr) 18 | #define CONSUME(stream, n) ((stream)->ptr += n) 19 | 20 | void skip_id3v2(stream* self) { 21 | if (BYTES_LEFT(self) < 10) { 22 | return; 23 | } 24 | uint8_t *data = READ_PTR(self); 25 | if (!( 26 | data[0] == 'I' && 27 | data[1] == 'D' && 28 | data[2] == '3' && 29 | data[3] != 0xff && 30 | data[4] != 0xff && 31 | (data[5] & 0x1f) == 0 && 32 | (data[6] & 0x80) == 0 && 33 | (data[7] & 0x80) == 0 && 34 | (data[8] & 0x80) == 0 && 35 | (data[9] & 0x80) == 0)) { 36 | return; 37 | } 38 | uint32_t size = (data[6] << 21) | (data[7] << 14) | (data[8] << 7) | (data[9]); 39 | size += 10; // size excludes the "header" (but not the "extended header") 40 | CONSUME(self, size + 10); 41 | } 42 | 43 | bool mp3file_find_sync_word(stream* self) { 44 | int offset = MP3FindSyncWord(READ_PTR(self), BYTES_LEFT(self)); 45 | if (offset >= 0) { 46 | CONSUME(self, offset); 47 | return true; 48 | } 49 | return false; 50 | } 51 | 52 | void fatal(const char *msg) { fprintf(stderr, "%s\n", msg); exit(1); } 53 | void perror_fatal(const char *msg) { perror(msg); exit(1); } 54 | 55 | bool probable_overflow(int16_t a, int16_t b) { 56 | if(a > 32700 && b < -32700) { 57 | return true; 58 | } else if(b > 32700 && a < -32700) { 59 | return true; 60 | } else { 61 | return false; 62 | } 63 | } 64 | 65 | void look_for_overflow(int16_t *ptr, size_t os, int frame) { 66 | for(size_t i=2; i 4 | maintainer=Dean Miller 5 | sentence=mp3 decoder 6 | paragraph= 7 | category=Data Processing 8 | url=https://github.com/adafruit/Adafruit_MP3 9 | architectures=* 10 | depends=Adafruit SPIFlash, SdFat - Adafruit Fork, SD 11 | -------------------------------------------------------------------------------- /src/Adafruit_MP3.h: -------------------------------------------------------------------------------- 1 | #ifndef LIB_ADAFRUIT_MP3_H 2 | #define LIB_ADAFRUIT_MP3_H 3 | 4 | #include "Arduino.h" 5 | 6 | #if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__)|| defined(NRF52) // teensy 3.6, 3.5, 3.1/2, or Adafruit Feather nRF52 7 | #define ARM_MATH_CM4 8 | #endif 9 | 10 | #include "arm_math.h" 11 | #include "mp3dec.h" 12 | 13 | //TODO: decide on a reasonable buffer size 14 | #if defined(NRF52) 15 | #define MP3_OUTBUF_SIZE (4 * 1024) 16 | #define MP3_INBUF_SIZE (2 * 1024) 17 | 18 | #define BUFFER_LOWER_THRESH (1 * 1024) 19 | #else 20 | #define MP3_OUTBUF_SIZE (4 * 1024) 21 | #define MP3_INBUF_SIZE (2 * 1024) 22 | 23 | #define BUFFER_LOWER_THRESH (1 * 1024) 24 | #endif 25 | 26 | #define MP3_SAMPLE_RATE_DEFAULT 44100 27 | 28 | #if defined(__SAMD51__) // feather/metro m4 29 | 30 | #define MP3_TC TC2 31 | #define MP3_IRQn TC2_IRQn 32 | #define MP3_Handler TC2_Handler 33 | #define MP3_GCLK_ID TC2_GCLK_ID 34 | #define MP3_DMA_TRIGGER TC2_DMAC_ID_MC_0 35 | 36 | #elif defined(NRF52) 37 | 38 | #define MP3_TIMER NRF_TIMER1 39 | #define MP3_IRQn TIMER1_IRQn 40 | #define MP3_Handler TIMER1_IRQHandler 41 | 42 | #endif 43 | 44 | struct Adafruit_MP3_outbuf { 45 | volatile int count; 46 | int16_t buffer[MP3_OUTBUF_SIZE]; 47 | }; 48 | 49 | class Adafruit_MP3 { 50 | public: 51 | Adafruit_MP3() : hMP3Decoder() { inbufend = (inBuf + MP3_INBUF_SIZE); } 52 | ~Adafruit_MP3() { MP3FreeDecoder(hMP3Decoder); }; 53 | bool begin(); 54 | void setBufferCallback(int (*fun_ptr)(uint8_t *, int)); 55 | void setSampleReadyCallback(void (*fun_ptr)(int16_t, int16_t)); 56 | 57 | void play(); 58 | void pause(); 59 | void resume(); 60 | 61 | int tick(); 62 | 63 | #if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__) // teensy 3.6, 3.5, or 3.1/2 64 | static IntervalTimer _MP3Timer; 65 | static uint32_t currentPeriod; 66 | #endif 67 | 68 | static uint8_t numChannels; 69 | 70 | protected: 71 | #if defined(__SAMD51__) // feather/metro m4 72 | Tc *_tc; 73 | #endif 74 | HMP3Decoder hMP3Decoder; 75 | 76 | volatile int bytesLeft; 77 | uint8_t *readPtr; 78 | uint8_t *writePtr; 79 | uint8_t inBuf[MP3_INBUF_SIZE]; 80 | uint8_t *inbufend; 81 | bool playing = false; 82 | 83 | int (*bufferCallback)(uint8_t *, int); 84 | int findID3Offset(uint8_t *readPtr); 85 | 86 | }; 87 | 88 | class Adafruit_MP3_DMA : public Adafruit_MP3 { 89 | public: 90 | Adafruit_MP3_DMA() : Adafruit_MP3() { 91 | framebuf = NULL; 92 | decodeCallback = NULL; 93 | } 94 | ~Adafruit_MP3_DMA() { 95 | if(framebuf != NULL) free(framebuf); 96 | } 97 | 98 | void getBuffers(int16_t **ping, int16_t **pong); 99 | void setDecodeCallback(void (*fun_ptr)(int16_t *, int)) { decodeCallback = fun_ptr; } 100 | 101 | void play(); 102 | int fill(); 103 | private: 104 | int16_t *framebuf, *leftover; 105 | int leftoverSamples; 106 | MP3FrameInfo frameInfo; 107 | void (*decodeCallback)(int16_t *, int); 108 | }; 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /src/assembly.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * assembly.h - assembly language functions and prototypes for supported platforms 42 | * 43 | * - inline rountines with access to 64-bit multiply results 44 | * - x86 (_WIN32) and ARM (ARM_ADS, _WIN32_WCE) versions included 45 | * - some inline functions are mix of asm and C for speed 46 | * - some functions are in native asm files, so only the prototype is given here 47 | * 48 | * MULSHIFT32(x, y) signed multiply of two 32-bit integers (x and y), returns top 32 bits of 64-bit result 49 | * FASTABS(x) branchless absolute value of signed integer x 50 | * CLZ(x) count leading zeros in x 51 | * MADD64(sum, x, y) (Windows only) sum [64-bit] += x [32-bit] * y [32-bit] 52 | * SHL64(sum, x, y) (Windows only) 64-bit left shift using __int64 53 | * SAR64(sum, x, y) (Windows only) 64-bit right shift using __int64 54 | */ 55 | 56 | #ifndef _ASSEMBLY_H 57 | #define _ASSEMBLY_H 58 | 59 | #ifdef __cplusplus 60 | extern "C" { 61 | #endif 62 | 63 | #if (defined _WIN32 && !defined _WIN32_WCE) || (defined __WINS__ && defined _SYMBIAN) || defined(_OPENWAVE_SIMULATOR) || defined(WINCE_EMULATOR) /* Symbian emulator for Ix86 */ 64 | 65 | #pragma warning( disable : 4035 ) /* complains about inline asm not returning a value */ 66 | 67 | static __inline int MULSHIFT32(int x, int y) 68 | { 69 | __asm { 70 | mov eax, x 71 | imul y 72 | mov eax, edx 73 | } 74 | } 75 | 76 | static __inline int FASTABS(int x) 77 | { 78 | int sign; 79 | 80 | sign = x >> (sizeof(int) * 8 - 1); 81 | x ^= sign; 82 | x -= sign; 83 | 84 | return x; 85 | } 86 | 87 | static __inline int CLZ(int x) 88 | { 89 | int numZeros; 90 | 91 | if (!x) 92 | return (sizeof(int) * 8); 93 | 94 | numZeros = 0; 95 | while (!(x & 0x80000000)) { 96 | numZeros++; 97 | x <<= 1; 98 | } 99 | 100 | return numZeros; 101 | } 102 | 103 | /* MADD64, SHL64, SAR64: 104 | * write in assembly to avoid dependency on run-time lib for 64-bit shifts, muls 105 | * (sometimes compiler thunks to function calls instead of code generating) 106 | * required for Symbian emulator 107 | */ 108 | #ifdef __CW32__ 109 | typedef long long Word64; 110 | #else 111 | typedef __int64 Word64; 112 | #endif 113 | 114 | static __inline Word64 MADD64(Word64 sum, int x, int y) 115 | { 116 | unsigned int sumLo = ((unsigned int *)&sum)[0]; 117 | int sumHi = ((int *)&sum)[1]; 118 | 119 | __asm { 120 | mov eax, x 121 | imul y 122 | add eax, sumLo 123 | adc edx, sumHi 124 | } 125 | 126 | /* equivalent to return (sum + ((__int64)x * y)); */ 127 | } 128 | 129 | static __inline Word64 SHL64(Word64 x, int n) 130 | { 131 | unsigned int xLo = ((unsigned int *)&x)[0]; 132 | int xHi = ((int *)&x)[1]; 133 | unsigned char nb = (unsigned char)n; 134 | 135 | if (n < 32) { 136 | __asm { 137 | mov edx, xHi 138 | mov eax, xLo 139 | mov cl, nb 140 | shld edx, eax, cl 141 | shl eax, cl 142 | } 143 | } else if (n < 64) { 144 | /* shl masks cl to 0x1f */ 145 | __asm { 146 | mov edx, xLo 147 | mov cl, nb 148 | xor eax, eax 149 | shl edx, cl 150 | } 151 | } else { 152 | __asm { 153 | xor edx, edx 154 | xor eax, eax 155 | } 156 | } 157 | } 158 | 159 | static __inline Word64 SAR64(Word64 x, int n) 160 | { 161 | unsigned int xLo = ((unsigned int *)&x)[0]; 162 | int xHi = ((int *)&x)[1]; 163 | unsigned char nb = (unsigned char)n; 164 | 165 | if (n < 32) { 166 | __asm { 167 | mov edx, xHi 168 | mov eax, xLo 169 | mov cl, nb 170 | shrd eax, edx, cl 171 | sar edx, cl 172 | } 173 | } else if (n < 64) { 174 | /* sar masks cl to 0x1f */ 175 | __asm { 176 | mov edx, xHi 177 | mov eax, xHi 178 | mov cl, nb 179 | sar edx, 31 180 | sar eax, cl 181 | } 182 | } else { 183 | __asm { 184 | sar xHi, 31 185 | mov eax, xHi 186 | mov edx, xHi 187 | } 188 | } 189 | } 190 | 191 | #elif (defined _WIN32) && (defined _WIN32_WCE) 192 | 193 | /* use asm function for now (EVC++ 3.0 does horrible job compiling __int64 version) */ 194 | #define MULSHIFT32 xmp3_MULSHIFT32 195 | int MULSHIFT32(int x, int y); 196 | 197 | static __inline int FASTABS(int x) 198 | { 199 | int sign; 200 | 201 | sign = x >> (sizeof(int) * 8 - 1); 202 | x ^= sign; 203 | x -= sign; 204 | 205 | return x; 206 | } 207 | 208 | static __inline int CLZ(int x) 209 | { 210 | int numZeros; 211 | 212 | if (!x) 213 | return (sizeof(int) * 8); 214 | 215 | numZeros = 0; 216 | while (!(x & 0x80000000)) { 217 | numZeros++; 218 | x <<= 1; 219 | } 220 | 221 | return numZeros; 222 | } 223 | 224 | #elif defined ARM_ADS 225 | 226 | static __inline int MULSHIFT32(int x, int y) 227 | { 228 | /* important rules for smull RdLo, RdHi, Rm, Rs: 229 | * RdHi and Rm can't be the same register 230 | * RdLo and Rm can't be the same register 231 | * RdHi and RdLo can't be the same register 232 | * Note: Rs determines early termination (leading sign bits) so if you want to specify 233 | * which operand is Rs, put it in the SECOND argument (y) 234 | * For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter 235 | * which one is returned. (If this were a function call, returning y (R1) would 236 | * require an extra "mov r0, r1") 237 | */ 238 | int zlow; 239 | __asm { 240 | smull zlow,y,x,y 241 | } 242 | 243 | return y; 244 | } 245 | 246 | static __inline int FASTABS(int x) 247 | { 248 | int t=0; /*Really is not necessary to initialiaze only to avoid warning*/ 249 | 250 | __asm { 251 | eor t, x, x, asr #31 252 | sub t, t, x, asr #31 253 | } 254 | 255 | return t; 256 | } 257 | 258 | static __inline int CLZ(int x) 259 | { 260 | int numZeros; 261 | 262 | if (!x) 263 | return (sizeof(int) * 8); 264 | 265 | numZeros = 0; 266 | while (!(x & 0x80000000)) { 267 | numZeros++; 268 | x <<= 1; 269 | } 270 | 271 | return numZeros; 272 | } 273 | 274 | #elif defined(__GNUC__) && (defined(ARM) || defined(__ARMEL__)) && (__ARM_ARCH >= 7) 275 | 276 | static __inline int MULSHIFT32(int x, int y) 277 | { 278 | /* important rules for smull RdLo, RdHi, Rm, Rs: 279 | * RdHi and Rm can't be the same register 280 | * RdLo and Rm can't be the same register 281 | * RdHi and RdLo can't be the same register 282 | * Note: Rs determines early termination (leading sign bits) so if you want to specify 283 | * which operand is Rs, put it in the SECOND argument (y) 284 | * For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter 285 | * which one is returned. (If this were a function call, returning y (R1) would 286 | * require an extra "mov r0, r1") 287 | */ 288 | int zlow; 289 | __asm__ volatile ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y)) ; 290 | 291 | return y; 292 | } 293 | 294 | static __inline int FASTABS(int x) 295 | { 296 | int t=0; /*Really is not necessary to initialiaze only to avoid warning*/ 297 | 298 | __asm__ volatile ( 299 | "eor %0,%2,%2, asr #31;" 300 | "sub %0,%1,%2, asr #31;" 301 | : "=&r" (t) 302 | : "0" (t), "r" (x) 303 | ); 304 | 305 | return t; 306 | } 307 | 308 | static __inline int CLZ(int x) 309 | { 310 | int numZeros; 311 | 312 | if (!x) 313 | return (sizeof(int) * 8); 314 | 315 | numZeros = 0; 316 | while (!(x & 0x80000000)) { 317 | numZeros++; 318 | x <<= 1; 319 | } 320 | 321 | return numZeros; 322 | } 323 | 324 | typedef signed long long int Word64; // 64-bit signed integer. 325 | typedef union _U64 { 326 | Word64 w64; 327 | struct { 328 | /* ARM ADS = little endian */ 329 | unsigned int lo32; 330 | signed int hi32; 331 | } r; 332 | } U64; 333 | 334 | static __inline Word64 MADD64(Word64 sum64, int x, int y) 335 | { 336 | U64 u; 337 | u.w64 = sum64; 338 | 339 | __asm__ volatile ("smlal %0,%1,%2,%3" : "+&r" (u.r.lo32), "+&r" (u.r.hi32) : "r" (x), "r" (y) : "cc"); 340 | 341 | return u.w64; 342 | } 343 | 344 | __attribute__((__always_inline__)) static __inline Word64 SAR64(Word64 x, int n) 345 | { 346 | unsigned int xLo = (unsigned int) x; 347 | int xHi = (int) (x >> 32); 348 | int nComp = 32-n; 349 | int tmp; 350 | // Shortcut: n is always < 32. 351 | __asm__ __volatile__( "lsl %2, %0, %3\n\t" // tmp <- xHi<<(32-n) 352 | "asr %0, %0, %4\n\t" // xHi <- xHi>>n 353 | "lsr %1, %1, %4\n\t" // xLo <- xLo>>n 354 | "orr %1, %2\n\t" // xLo <= xLo || tmp 355 | : "+&r" (xHi), "+r" (xLo), "=&r" (tmp) 356 | : "r" (nComp), "r" (n) ); 357 | x = xLo | ((Word64)xHi << 32); 358 | return( x ); 359 | } 360 | #elif defined(__GNUC__) && defined(__AVR32_UC__) 361 | 362 | typedef signed long long int Word64; // 64-bit signed integer. 363 | 364 | 365 | __attribute__((__always_inline__)) static __inline int MULSHIFT32(int x, int y) 366 | { 367 | signed long long int s64Tmp; 368 | __asm__ __volatile__( "muls.d %0, %1, %2" 369 | : "=r" (s64Tmp) 370 | : "r" (x), "r" (y) ); 371 | return( s64Tmp >> 32 ); 372 | } 373 | 374 | __attribute__((__always_inline__)) static __inline int FASTABS(int x) 375 | { 376 | int tmp; 377 | __asm__ __volatile__( "abs %0" 378 | : "=r" (tmp) 379 | : "r" (x) ); 380 | return tmp; 381 | 382 | } 383 | 384 | 385 | __attribute__((__always_inline__)) static __inline int CLZ(int x) 386 | { 387 | int tmp; 388 | __asm__ __volatile__( "clz %0,%1" 389 | : "=r" (tmp) 390 | : "r" (x) ); 391 | return tmp; 392 | } 393 | 394 | 395 | /* MADD64, SAR64: 396 | * write in assembly to avoid dependency on run-time lib for 64-bit shifts, muls 397 | * (sometimes compiler do function calls instead of code generating) 398 | */ 399 | __attribute__((__always_inline__)) static __inline Word64 MADD64(Word64 sum, int x, int y) 400 | { 401 | __asm__ __volatile__( "macs.d %0, %1, %2" 402 | : "+r" (sum) 403 | : "r" (x), "r" (y) ); 404 | return( sum ); 405 | } 406 | 407 | 408 | __attribute__((__always_inline__)) static __inline Word64 SAR64(Word64 x, int n) 409 | { 410 | unsigned int xLo = (unsigned int) x; 411 | int xHi = (int) (x >> 32); 412 | int nComp = 32-n; 413 | int tmp; 414 | // Shortcut: n is always < 32. 415 | __asm__ __volatile__( "lsl %2, %0, %3\n\t" // tmp <- xHi<<(32-n) 416 | "asr %0, %0, %4\n\t" // xHi <- xHi>>n 417 | "lsr %1, %1, %4\n\t" // xLo <- xLo>>n 418 | "or %1, %2\n\t" // xLo <= xLo || tmp 419 | : "+&r" (xHi), "+r" (xLo), "=&r" (tmp) 420 | : "r" (nComp), "r" (n) ); 421 | x = xLo | ((Word64)xHi << 32); 422 | return( x ); 423 | } 424 | 425 | #elif (defined(__CORTEX_M) && __CORTEX_M == 0x04U) || defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__) /* teensy 3.6, 3.5, or 3.1/2 */ 426 | 427 | /* ARM cortex m4 */ 428 | 429 | typedef signed long long int Word64; // 64-bit signed integer. 430 | 431 | 432 | static __inline int MULSHIFT32(int x, int y) 433 | { 434 | /* important rules for smull RdLo, RdHi, Rm, Rs: 435 | * RdHi and Rm can't be the same register 436 | * RdLo and Rm can't be the same register 437 | * RdHi and RdLo can't be the same register 438 | * Note: Rs determines early termination (leading sign bits) so if you want to specify 439 | * which operand is Rs, put it in the SECOND argument (y) 440 | * For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter 441 | * which one is returned. (If this were a function call, returning y (R1) would 442 | * require an extra "mov r0, r1") 443 | */ 444 | int zlow; 445 | __asm__ volatile ("smull %0,%1,%2,%3" : "=&r" (zlow), "=r" (y) : "r" (x), "1" (y)) ; 446 | 447 | return y; 448 | } 449 | 450 | static __inline int FASTABS(int x) 451 | { 452 | int sign; 453 | 454 | sign = x >> (sizeof(int) * 8 - 1); 455 | x ^= sign; 456 | x -= sign; 457 | 458 | return x; 459 | } 460 | 461 | static __inline int CLZ(int x) 462 | { 463 | #if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__) /* teensy 3.6, 3.5, or 3.1/2 */ 464 | return __builtin_clz(x); 465 | #else 466 | return __CLZ(x); 467 | #endif 468 | } 469 | 470 | typedef union _U64 { 471 | Word64 w64; 472 | struct { 473 | /* ARM ADS = little endian */ 474 | unsigned int lo32; 475 | signed int hi32; 476 | } r; 477 | } U64; 478 | 479 | static __inline Word64 MADD64(Word64 sum64, int x, int y) 480 | { 481 | U64 u; 482 | u.w64 = sum64; 483 | 484 | __asm__ volatile ("smlal %0,%1,%2,%3" : "+&r" (u.r.lo32), "+&r" (u.r.hi32) : "r" (x), "r" (y) : "cc"); 485 | 486 | return u.w64; 487 | } 488 | 489 | 490 | __attribute__((__always_inline__)) static __inline Word64 SAR64(Word64 x, int n) 491 | { 492 | unsigned int xLo = (unsigned int) x; 493 | int xHi = (int) (x >> 32); 494 | int nComp = 32-n; 495 | int tmp; 496 | // Shortcut: n is always < 32. 497 | __asm__ __volatile__( "lsl %2, %0, %3\n\t" // tmp <- xHi<<(32-n) 498 | "asr %0, %0, %4\n\t" // xHi <- xHi>>n 499 | "lsr %1, %1, %4\n\t" // xLo <- xLo>>n 500 | "orr %1, %2\n\t" // xLo <= xLo || tmp 501 | : "+&r" (xHi), "+r" (xLo), "=&r" (tmp) 502 | : "r" (nComp), "r" (n) ); 503 | x = xLo | ((Word64)xHi << 32); 504 | return( x ); 505 | } 506 | 507 | //END cortex m4 508 | 509 | 510 | #else 511 | 512 | #include 513 | 514 | typedef int64_t Word64; 515 | 516 | static inline int MULSHIFT32(int x, int y) { 517 | return ((int64_t)x * y) >> 32; 518 | } 519 | 520 | static inline int FASTABS(int x) { 521 | #if defined(GNUC) 522 | return __builtin_abs(x); 523 | #else 524 | int sign = x >> 31; 525 | return (x ^ sign) - sign; 526 | #endif 527 | } 528 | 529 | static inline int CLZ(int x) { 530 | return x ? __builtin_clz(x) : 32; 531 | } 532 | 533 | static inline Word64 MADD64(Word64 sum, int x, int y) { 534 | return sum + (int64_t)x * y; 535 | } 536 | 537 | static inline Word64 SHL64(Word64 x, int n) { 538 | return x << n; 539 | } 540 | 541 | static inline Word64 SAR64(Word64 x, int n) { 542 | return x >> n; 543 | } 544 | 545 | #endif /* platforms */ 546 | 547 | #ifdef __cplusplus 548 | } 549 | #endif 550 | #endif /* _ASSEMBLY_H */ 551 | -------------------------------------------------------------------------------- /src/bitstream.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * bitstream.c - bitstream unpacking, frame header parsing, side info parsing 42 | **************************************************************************************/ 43 | 44 | #include "coder.h" 45 | #include "assembly.h" 46 | 47 | /************************************************************************************** 48 | * Function: SetBitstreamPointer 49 | * 50 | * Description: initialize bitstream reader 51 | * 52 | * Inputs: pointer to BitStreamInfo struct 53 | * number of bytes in bitstream 54 | * pointer to byte-aligned buffer of data to read from 55 | * 56 | * Outputs: filled bitstream info struct 57 | * 58 | * Return: none 59 | **************************************************************************************/ 60 | void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf) 61 | { 62 | /* init bitstream */ 63 | bsi->bytePtr = buf; 64 | bsi->iCache = 0; /* 4-byte unsigned int */ 65 | bsi->cachedBits = 0; /* i.e. zero bits in cache */ 66 | bsi->nBytes = nBytes; 67 | } 68 | 69 | /************************************************************************************** 70 | * Function: RefillBitstreamCache 71 | * 72 | * Description: read new data from bitstream buffer into bsi cache 73 | * 74 | * Inputs: pointer to initialized BitStreamInfo struct 75 | * 76 | * Outputs: updated bitstream info struct 77 | * 78 | * Return: none 79 | * 80 | * Notes: only call when iCache is completely drained (resets bitOffset to 0) 81 | * always loads 4 new bytes except when bsi->nBytes < 4 (end of buffer) 82 | * stores data as big-endian in cache, regardless of machine endian-ness 83 | * 84 | * TODO: optimize for ARM 85 | * possibly add little/big-endian modes for doing 32-bit loads 86 | **************************************************************************************/ 87 | static __inline void RefillBitstreamCache(BitStreamInfo *bsi) 88 | { 89 | int nBytes = bsi->nBytes; 90 | 91 | /* optimize for common case, independent of machine endian-ness */ 92 | if (nBytes >= 4) { 93 | bsi->iCache = (*bsi->bytePtr++) << 24; 94 | bsi->iCache |= (*bsi->bytePtr++) << 16; 95 | bsi->iCache |= (*bsi->bytePtr++) << 8; 96 | bsi->iCache |= (*bsi->bytePtr++); 97 | bsi->cachedBits = 32; 98 | bsi->nBytes -= 4; 99 | } else { 100 | bsi->iCache = 0; 101 | while (nBytes--) { 102 | bsi->iCache |= (*bsi->bytePtr++); 103 | bsi->iCache <<= 8; 104 | } 105 | bsi->iCache <<= ((3 - bsi->nBytes)*8); 106 | bsi->cachedBits = 8*bsi->nBytes; 107 | bsi->nBytes = 0; 108 | } 109 | } 110 | 111 | /************************************************************************************** 112 | * Function: GetBits 113 | * 114 | * Description: get bits from bitstream, advance bitstream pointer 115 | * 116 | * Inputs: pointer to initialized BitStreamInfo struct 117 | * number of bits to get from bitstream 118 | * 119 | * Outputs: updated bitstream info struct 120 | * 121 | * Return: the next nBits bits of data from bitstream buffer 122 | * 123 | * Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f 124 | * for speed, does not indicate error if you overrun bit buffer 125 | * if nBits = 0, returns 0 (useful for scalefactor unpacking) 126 | * 127 | * TODO: optimize for ARM 128 | **************************************************************************************/ 129 | unsigned int GetBits(BitStreamInfo *bsi, int nBits) 130 | { 131 | unsigned int data, lowBits; 132 | 133 | nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */ 134 | data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */ 135 | data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */ 136 | bsi->iCache <<= nBits; /* left-justify cache */ 137 | bsi->cachedBits -= nBits; /* how many bits have we drawn from the cache so far */ 138 | 139 | /* if we cross an int boundary, refill the cache */ 140 | if (bsi->cachedBits < 0) { 141 | lowBits = -bsi->cachedBits; 142 | RefillBitstreamCache(bsi); 143 | data |= bsi->iCache >> (32 - lowBits); /* get the low-order bits */ 144 | 145 | bsi->cachedBits -= lowBits; /* how many bits have we drawn from the cache so far */ 146 | bsi->iCache <<= lowBits; /* left-justify cache */ 147 | } 148 | 149 | return data; 150 | } 151 | 152 | /************************************************************************************** 153 | * Function: CalcBitsUsed 154 | * 155 | * Description: calculate how many bits have been read from bitstream 156 | * 157 | * Inputs: pointer to initialized BitStreamInfo struct 158 | * pointer to start of bitstream buffer 159 | * bit offset into first byte of startBuf (0-7) 160 | * 161 | * Outputs: none 162 | * 163 | * Return: number of bits read from bitstream, as offset from startBuf:startOffset 164 | **************************************************************************************/ 165 | int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset) 166 | { 167 | int bitsUsed; 168 | 169 | bitsUsed = (bsi->bytePtr - startBuf) * 8; 170 | bitsUsed -= bsi->cachedBits; 171 | bitsUsed -= startOffset; 172 | 173 | return bitsUsed; 174 | } 175 | 176 | /************************************************************************************** 177 | * Function: CheckPadBit 178 | * 179 | * Description: check whether padding byte is present in an MP3 frame 180 | * 181 | * Inputs: MP3DecInfo struct with valid FrameHeader struct 182 | * (filled by UnpackFrameHeader()) 183 | * 184 | * Outputs: none 185 | * 186 | * Return: 1 if pad bit is set, 0 if not, -1 if null input pointer 187 | **************************************************************************************/ 188 | int CheckPadBit(MP3DecInfo *mp3DecInfo) 189 | { 190 | FrameHeader *fh; 191 | 192 | /* validate pointers */ 193 | if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS) 194 | return -1; 195 | 196 | fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); 197 | 198 | return (fh->paddingBit ? 1 : 0); 199 | } 200 | 201 | /************************************************************************************** 202 | * Function: UnpackFrameHeader 203 | * 204 | * Description: parse the fields of the MP3 frame header 205 | * 206 | * Inputs: buffer pointing to a complete MP3 frame header (4 bytes, plus 2 if CRC) 207 | * 208 | * Outputs: filled frame header info in the MP3DecInfo structure 209 | * updated platform-specific FrameHeader struct 210 | * 211 | * Return: length (in bytes) of frame header (for caller to calculate offset to 212 | * first byte following frame header) 213 | * -1 if null frameHeader or invalid header 214 | * 215 | * TODO: check for valid modes, depending on capabilities of decoder 216 | * test CRC on actual stream (verify no endian problems) 217 | **************************************************************************************/ 218 | int UnpackFrameHeader(MP3DecInfo *mp3DecInfo, unsigned char *buf) 219 | { 220 | 221 | int verIdx; 222 | FrameHeader *fh; 223 | 224 | /* validate pointers and sync word */ 225 | if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || (buf[0] & SYNCWORDH) != SYNCWORDH || (buf[1] & SYNCWORDL) != SYNCWORDL) 226 | return -1; 227 | 228 | fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); 229 | 230 | /* read header fields - use bitmasks instead of GetBits() for speed, since format never varies */ 231 | verIdx = (buf[1] >> 3) & 0x03; 232 | fh->ver = (MPEGVersion)( verIdx == 0 ? MPEG25 : ((verIdx & 0x01) ? MPEG1 : MPEG2) ); 233 | fh->layer = 4 - ((buf[1] >> 1) & 0x03); /* easy mapping of index to layer number, 4 = error */ 234 | fh->crc = 1 - ((buf[1] >> 0) & 0x01); 235 | fh->brIdx = (buf[2] >> 4) & 0x0f; 236 | fh->srIdx = (buf[2] >> 2) & 0x03; 237 | fh->paddingBit = (buf[2] >> 1) & 0x01; 238 | fh->privateBit = (buf[2] >> 0) & 0x01; 239 | fh->sMode = (StereoMode)((buf[3] >> 6) & 0x03); /* maps to correct enum (see definition) */ 240 | fh->modeExt = (buf[3] >> 4) & 0x03; 241 | fh->copyFlag = (buf[3] >> 3) & 0x01; 242 | fh->origFlag = (buf[3] >> 2) & 0x01; 243 | fh->emphasis = (buf[3] >> 0) & 0x03; 244 | 245 | /* check parameters to avoid indexing tables with bad values */ 246 | if (fh->srIdx == 3 || fh->layer == 4 || fh->brIdx == 15) 247 | return -1; 248 | 249 | fh->sfBand = &sfBandTable[fh->ver][fh->srIdx]; /* for readability (we reference sfBandTable many times in decoder) */ 250 | if (fh->sMode != Joint) /* just to be safe (dequant, stproc check fh->modeExt) */ 251 | fh->modeExt = 0; 252 | 253 | /* init user-accessible data */ 254 | mp3DecInfo->nChans = (fh->sMode == Mono ? 1 : 2); 255 | mp3DecInfo->samprate = samplerateTab[fh->ver][fh->srIdx]; 256 | mp3DecInfo->nGrans = (fh->ver == MPEG1 ? NGRANS_MPEG1 : NGRANS_MPEG2); 257 | mp3DecInfo->nGranSamps = ((int)samplesPerFrameTab[fh->ver][fh->layer - 1]) / mp3DecInfo->nGrans; 258 | mp3DecInfo->layer = fh->layer; 259 | mp3DecInfo->version = fh->ver; 260 | 261 | /* get bitrate and nSlots from table, unless brIdx == 0 (free mode) in which case caller must figure it out himself 262 | * question - do we want to overwrite mp3DecInfo->bitrate with 0 each time if it's free mode, and 263 | * copy the pre-calculated actual free bitrate into it in mp3dec.c (according to the spec, 264 | * this shouldn't be necessary, since it should be either all frames free or none free) 265 | */ 266 | if (fh->brIdx) { 267 | mp3DecInfo->bitrate = ((int)bitrateTab[fh->ver][fh->layer - 1][fh->brIdx]) * 1000; 268 | 269 | /* nSlots = total frame bytes (from table) - sideInfo bytes - header - CRC (if present) + pad (if present) */ 270 | mp3DecInfo->nSlots = (int)slotTab[fh->ver][fh->srIdx][fh->brIdx] - 271 | (int)sideBytesTab[fh->ver][(fh->sMode == Mono ? 0 : 1)] - 272 | 4 - (fh->crc ? 2 : 0) + (fh->paddingBit ? 1 : 0); 273 | } 274 | 275 | /* load crc word, if enabled, and return length of frame header (in bytes) */ 276 | if (fh->crc) { 277 | fh->CRCWord = ((int)buf[4] << 8 | (int)buf[5] << 0); 278 | return 6; 279 | } else { 280 | fh->CRCWord = 0; 281 | return 4; 282 | } 283 | } 284 | 285 | /************************************************************************************** 286 | * Function: UnpackSideInfo 287 | * 288 | * Description: parse the fields of the MP3 side info header 289 | * 290 | * Inputs: MP3DecInfo structure filled by UnpackFrameHeader() 291 | * buffer pointing to the MP3 side info data 292 | * 293 | * Outputs: updated mainDataBegin in MP3DecInfo struct 294 | * updated private (platform-specific) SideInfo struct 295 | * 296 | * Return: length (in bytes) of side info data 297 | * -1 if null input pointers 298 | **************************************************************************************/ 299 | int UnpackSideInfo(MP3DecInfo *mp3DecInfo, unsigned char *buf) 300 | { 301 | int gr, ch, bd, nBytes; 302 | BitStreamInfo bitStreamInfo, *bsi; 303 | FrameHeader *fh; 304 | SideInfo *si; 305 | SideInfoSub *sis; 306 | 307 | /* validate pointers and sync word */ 308 | if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS) 309 | return -1; 310 | 311 | fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); 312 | si = ((SideInfo *)(mp3DecInfo->SideInfoPS)); 313 | 314 | bsi = &bitStreamInfo; 315 | if (fh->ver == MPEG1) { 316 | /* MPEG 1 */ 317 | nBytes = (fh->sMode == Mono ? SIBYTES_MPEG1_MONO : SIBYTES_MPEG1_STEREO); 318 | SetBitstreamPointer(bsi, nBytes, buf); 319 | si->mainDataBegin = GetBits(bsi, 9); 320 | si->privateBits = GetBits(bsi, (fh->sMode == Mono ? 5 : 3)); 321 | 322 | for (ch = 0; ch < mp3DecInfo->nChans; ch++) 323 | for (bd = 0; bd < MAX_SCFBD; bd++) 324 | si->scfsi[ch][bd] = GetBits(bsi, 1); 325 | } else { 326 | /* MPEG 2, MPEG 2.5 */ 327 | nBytes = (fh->sMode == Mono ? SIBYTES_MPEG2_MONO : SIBYTES_MPEG2_STEREO); 328 | SetBitstreamPointer(bsi, nBytes, buf); 329 | si->mainDataBegin = GetBits(bsi, 8); 330 | si->privateBits = GetBits(bsi, (fh->sMode == Mono ? 1 : 2)); 331 | } 332 | 333 | for(gr =0; gr < mp3DecInfo->nGrans; gr++) { 334 | for (ch = 0; ch < mp3DecInfo->nChans; ch++) { 335 | sis = &si->sis[gr][ch]; /* side info subblock for this granule, channel */ 336 | 337 | sis->part23Length = GetBits(bsi, 12); 338 | sis->nBigvals = GetBits(bsi, 9); 339 | sis->globalGain = GetBits(bsi, 8); 340 | sis->sfCompress = GetBits(bsi, (fh->ver == MPEG1 ? 4 : 9)); 341 | sis->winSwitchFlag = GetBits(bsi, 1); 342 | 343 | if(sis->winSwitchFlag) { 344 | /* this is a start, stop, short, or mixed block */ 345 | sis->blockType = GetBits(bsi, 2); /* 0 = normal, 1 = start, 2 = short, 3 = stop */ 346 | sis->mixedBlock = GetBits(bsi, 1); /* 0 = not mixed, 1 = mixed */ 347 | sis->tableSelect[0] = GetBits(bsi, 5); 348 | sis->tableSelect[1] = GetBits(bsi, 5); 349 | sis->tableSelect[2] = 0; /* unused */ 350 | sis->subBlockGain[0] = GetBits(bsi, 3); 351 | sis->subBlockGain[1] = GetBits(bsi, 3); 352 | sis->subBlockGain[2] = GetBits(bsi, 3); 353 | 354 | /* TODO - check logic */ 355 | if (sis->blockType == 0) { 356 | /* this should not be allowed, according to spec */ 357 | sis->nBigvals = 0; 358 | sis->part23Length = 0; 359 | sis->sfCompress = 0; 360 | } else if (sis->blockType == 2 && sis->mixedBlock == 0) { 361 | /* short block, not mixed */ 362 | sis->region0Count = 8; 363 | } else { 364 | /* start, stop, or short-mixed */ 365 | sis->region0Count = 7; 366 | } 367 | sis->region1Count = 20 - sis->region0Count; 368 | } else { 369 | /* this is a normal block */ 370 | sis->blockType = 0; 371 | sis->mixedBlock = 0; 372 | sis->tableSelect[0] = GetBits(bsi, 5); 373 | sis->tableSelect[1] = GetBits(bsi, 5); 374 | sis->tableSelect[2] = GetBits(bsi, 5); 375 | sis->region0Count = GetBits(bsi, 4); 376 | sis->region1Count = GetBits(bsi, 3); 377 | } 378 | sis->preFlag = (fh->ver == MPEG1 ? GetBits(bsi, 1) : 0); 379 | sis->sfactScale = GetBits(bsi, 1); 380 | sis->count1TableSelect = GetBits(bsi, 1); 381 | } 382 | } 383 | mp3DecInfo->mainDataBegin = si->mainDataBegin; /* needed by main decode loop */ 384 | 385 | ASSERT(nBytes == CalcBitsUsed(bsi, buf, 0) >> 3); 386 | 387 | return nBytes; 388 | } 389 | 390 | -------------------------------------------------------------------------------- /src/buffers.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * buffers.c - allocation and freeing of internal MP3 decoder buffers 42 | * 43 | * All memory allocation for the codec is done in this file, so if you don't want 44 | * to use other the default system malloc() and free() for heap management this is 45 | * the only file you'll need to change. 46 | **************************************************************************************/ 47 | 48 | #include "coder.h" 49 | 50 | #ifndef _WIN32 51 | #ifdef DEMO_HELIX_FOOTPRINT 52 | #include "dv_debug_usart.h" 53 | #endif 54 | #endif 55 | 56 | /************************************************************************************** 57 | * Function: ClearBuffer 58 | * 59 | * Description: fill buffer with 0's 60 | * 61 | * Inputs: pointer to buffer 62 | * number of bytes to fill with 0 63 | * 64 | * Outputs: cleared buffer 65 | * 66 | * Return: none 67 | * 68 | * Notes: slow, platform-independent equivalent to memset(buf, 0, nBytes) 69 | **************************************************************************************/ 70 | #ifndef MPDEC_ALLOCATOR 71 | static void ClearBuffer(void *buf, int nBytes) 72 | { 73 | int i; 74 | unsigned char *cbuf = (unsigned char *)buf; 75 | 76 | for (i = 0; i < nBytes; i++) 77 | cbuf[i] = 0; 78 | 79 | return; 80 | } 81 | #endif 82 | 83 | /************************************************************************************** 84 | * Function: AllocateBuffers 85 | * 86 | * Description: allocate all the memory needed for the MP3 decoder 87 | * 88 | * Inputs: none 89 | * 90 | * Outputs: none 91 | * 92 | * Return: pointer to MP3DecInfo structure (initialized with pointers to all 93 | * the internal buffers needed for decoding, all other members of 94 | * MP3DecInfo structure set to 0) 95 | * 96 | * Notes: if one or more mallocs fail, function frees any buffers already 97 | * allocated before returning 98 | **************************************************************************************/ 99 | MP3DecInfo *AllocateBuffers(void) 100 | { 101 | MP3DecInfo *mp3DecInfo; 102 | #ifdef MPDEC_ALLOCATOR 103 | FrameHeader *fh; 104 | SideInfo *si; 105 | ScaleFactorInfo *sfi; 106 | HuffmanInfo *hi; 107 | DequantInfo *di; 108 | IMDCTInfo *mi; 109 | SubbandInfo *sbi; 110 | 111 | mp3DecInfo = (MP3DecInfo *)MPDEC_ALLOCATOR(sizeof(MP3DecInfo)); 112 | if (!mp3DecInfo) 113 | { 114 | #ifndef _WIN32 115 | #ifdef DEMO_HELIX_FOOTPRINT 116 | sprintf(COPY_DEBUG_BUFFER,"mp3DecInfo size: %d\n", (int)sizeof(MP3DecInfo)); 117 | DV_DEBUG_USART_Trace( COPY_DEBUG_BUFFER ); 118 | #endif 119 | #endif 120 | return 0; 121 | } 122 | 123 | hi = (HuffmanInfo *) MPDEC_ALLOCATOR(sizeof(HuffmanInfo)); 124 | sbi = (SubbandInfo *) MPDEC_ALLOCATOR(sizeof(SubbandInfo)); 125 | mi = (IMDCTInfo *) MPDEC_ALLOCATOR(sizeof(IMDCTInfo)); 126 | di = (DequantInfo *) MPDEC_ALLOCATOR(sizeof(DequantInfo)); 127 | si = (SideInfo *) MPDEC_ALLOCATOR(sizeof(SideInfo)); 128 | sfi = (ScaleFactorInfo *) MPDEC_ALLOCATOR(sizeof(ScaleFactorInfo)); 129 | fh = (FrameHeader *) MPDEC_ALLOCATOR(sizeof(FrameHeader)); 130 | 131 | if (!fh || !si || !sfi || !hi || !di || !mi || !sbi) { 132 | #ifndef _WIN32 133 | #ifdef DEMO_HELIX_FOOTPRINT 134 | sprintf(COPY_DEBUG_BUFFER,"mp3DecInfo:%d[%d] | fh:%d[%d] | si:%d[%d] \ 135 | | sfi:%d[%d] | hi:%d[%d] | di:%d[%d] | mi:%d[%d] | sbi:%d[%d]\n", 136 | (int)mp3DecInfo, (int)sizeof(MP3DecInfo), (int)fh, (int)sizeof(FrameHeader), 137 | (int)si, (int)sizeof(SideInfo), (int)sfi, (int)sizeof(ScaleFactorInfo), 138 | (int)hi, (int)sizeof(HuffmanInfo), (int)di, (int)sizeof(DequantInfo), 139 | (int)mi, (int)sizeof(IMDCTInfo), (int)sbi, (int)sizeof(SubbandInfo) ); 140 | DV_DEBUG_USART_Trace( COPY_DEBUG_BUFFER ); 141 | #endif 142 | #endif 143 | FreeBuffers(mp3DecInfo); // safe to call - only frees memory that was successfully allocated 144 | return 0; 145 | } 146 | #else 147 | 148 | // Buffers: 149 | static char s_mp3DecInfo[sizeof(MP3DecInfo)]; 150 | static char fh[sizeof(FrameHeader)]; 151 | static char si[sizeof(SideInfo)]; 152 | static char sfi[sizeof(ScaleFactorInfo)]; 153 | static char hi[sizeof(HuffmanInfo)]; 154 | static char di[sizeof(DequantInfo)]; 155 | static char mi[sizeof(IMDCTInfo)]; 156 | static char sbi[sizeof(SubbandInfo)]; 157 | 158 | mp3DecInfo = (MP3DecInfo *)s_mp3DecInfo; 159 | ClearBuffer(mp3DecInfo, sizeof(MP3DecInfo)); 160 | 161 | /* important to do this - DSP primitives assume a bunch of state variables are 0 on first use */ 162 | ClearBuffer(fh, sizeof(FrameHeader)); 163 | ClearBuffer(si, sizeof(SideInfo)); 164 | ClearBuffer(sfi, sizeof(ScaleFactorInfo)); 165 | ClearBuffer(hi, sizeof(HuffmanInfo)); 166 | ClearBuffer(di, sizeof(DequantInfo)); 167 | ClearBuffer(mi, sizeof(IMDCTInfo)); 168 | ClearBuffer(sbi, sizeof(SubbandInfo)); 169 | 170 | #endif 171 | 172 | mp3DecInfo->FrameHeaderPS = (void *)fh; 173 | mp3DecInfo->SideInfoPS = (void *)si; 174 | mp3DecInfo->ScaleFactorInfoPS = (void *)sfi; 175 | mp3DecInfo->HuffmanInfoPS = (void *)hi; 176 | mp3DecInfo->DequantInfoPS = (void *)di; 177 | mp3DecInfo->IMDCTInfoPS = (void *)mi; 178 | mp3DecInfo->SubbandInfoPS = (void *)sbi; 179 | 180 | #ifndef _WIN32 181 | #ifdef DEMO_HELIX_FOOTPRINT 182 | sprintf(COPY_DEBUG_BUFFER, "Total decoder malloc size: %d\n", 183 | (int)(sizeof(MP3DecInfo) + sizeof(FrameHeader) + sizeof(SideInfo) 184 | + sizeof(ScaleFactorInfo) + sizeof(HuffmanInfo) + sizeof(DequantInfo) 185 | + sizeof(IMDCTInfo) + sizeof(SubbandInfo))); 186 | DV_DEBUG_USART_Trace( COPY_DEBUG_BUFFER ); 187 | #endif 188 | #endif 189 | 190 | return mp3DecInfo; 191 | } 192 | 193 | #ifdef MPDEC_FREE 194 | #define SAFE_FREE(x) {if (x) MPDEC_FREE(x); (x) = 0;} /* helper macro */ 195 | #else 196 | #define SAFE_FREE(x) { (x) = 0; } 197 | #endif 198 | 199 | /************************************************************************************** 200 | * Function: FreeBuffers 201 | * 202 | * Description: frees all the memory used by the MP3 decoder 203 | * 204 | * Inputs: pointer to initialized MP3DecInfo structure 205 | * 206 | * Outputs: none 207 | * 208 | * Return: none 209 | * 210 | * Notes: safe to call even if some buffers were not allocated (uses SAFE_FREE) 211 | **************************************************************************************/ 212 | void FreeBuffers(MP3DecInfo *mp3DecInfo) 213 | { 214 | if (!mp3DecInfo) 215 | return; 216 | 217 | SAFE_FREE(mp3DecInfo->FrameHeaderPS); 218 | SAFE_FREE(mp3DecInfo->SideInfoPS); 219 | SAFE_FREE(mp3DecInfo->ScaleFactorInfoPS); 220 | SAFE_FREE(mp3DecInfo->HuffmanInfoPS); 221 | SAFE_FREE(mp3DecInfo->DequantInfoPS); 222 | SAFE_FREE(mp3DecInfo->IMDCTInfoPS); 223 | SAFE_FREE(mp3DecInfo->SubbandInfoPS); 224 | 225 | SAFE_FREE(mp3DecInfo); 226 | } 227 | -------------------------------------------------------------------------------- /src/coder.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * coder.h - private, implementation-specific header file 42 | **************************************************************************************/ 43 | 44 | #ifndef _CODER_H 45 | #define _CODER_H 46 | 47 | #include "mp3common.h" 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | #if defined(ASSERT) 54 | #undef ASSERT 55 | #endif 56 | #if defined(_WIN32) && defined(_M_IX86) && (defined (_DEBUG) || defined (REL_ENABLE_ASSERTS)) 57 | #define ASSERT(x) if (!(x)) __asm int 3; 58 | #else 59 | #define ASSERT(x) /* do nothing */ 60 | #endif 61 | 62 | #ifndef MAX 63 | #define MAX(a,b) ((a) > (b) ? (a) : (b)) 64 | #endif 65 | 66 | #ifndef MIN 67 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) 68 | #endif 69 | 70 | /* clip to range [-2^n, 2^n - 1] */ 71 | #define CLIP_2N(y, n) { \ 72 | int sign = (y) >> 31; \ 73 | if (sign != (y) >> (n)) { \ 74 | (y) = sign ^ ((1 << (n)) - 1); \ 75 | } \ 76 | } 77 | 78 | #define SIBYTES_MPEG1_MONO 17 79 | #define SIBYTES_MPEG1_STEREO 32 80 | #define SIBYTES_MPEG2_MONO 9 81 | #define SIBYTES_MPEG2_STEREO 17 82 | 83 | /* number of fraction bits for pow43Tab (see comments there) */ 84 | #define POW43_FRACBITS_LOW 22 85 | #define POW43_FRACBITS_HIGH 12 86 | 87 | #define DQ_FRACBITS_OUT 25 /* number of fraction bits in output of dequant */ 88 | #define IMDCT_SCALE 2 /* additional scaling (by sqrt(2)) for fast IMDCT36 */ 89 | 90 | #define HUFF_PAIRTABS 32 91 | #define BLOCK_SIZE 18 92 | #define NBANDS 32 93 | #define MAX_REORDER_SAMPS ((192-126)*3) /* largest critical band for short blocks (see sfBandTable) */ 94 | #define VBUF_LENGTH (17 * 2 * NBANDS) /* for double-sized vbuf FIFO */ 95 | 96 | /* additional external symbols to name-mangle for static linking */ 97 | #define SetBitstreamPointer STATNAME(SetBitstreamPointer) 98 | #define GetBits STATNAME(GetBits) 99 | #define CalcBitsUsed STATNAME(CalcBitsUsed) 100 | #define DequantChannel STATNAME(DequantChannel) 101 | #define MidSideProc STATNAME(MidSideProc) 102 | #define IntensityProcMPEG1 STATNAME(IntensityProcMPEG1) 103 | #define IntensityProcMPEG2 STATNAME(IntensityProcMPEG2) 104 | #define PolyphaseMono STATNAME(PolyphaseMono) 105 | #define PolyphaseStereo STATNAME(PolyphaseStereo) 106 | #define FDCT32 STATNAME(FDCT32) 107 | 108 | #define ISFMpeg1 STATNAME(ISFMpeg1) 109 | #define ISFMpeg2 STATNAME(ISFMpeg2) 110 | #define ISFIIP STATNAME(ISFIIP) 111 | #define uniqueIDTab STATNAME(uniqueIDTab) 112 | #define coef32 STATNAME(coef32) 113 | #define polyCoef STATNAME(polyCoef) 114 | #define csa STATNAME(csa) 115 | #define imdctWin STATNAME(imdctWin) 116 | 117 | #define huffTable STATNAME(huffTable) 118 | #define huffTabOffset STATNAME(huffTabOffset) 119 | #define huffTabLookup STATNAME(huffTabLookup) 120 | #define quadTable STATNAME(quadTable) 121 | #define quadTabOffset STATNAME(quadTabOffset) 122 | #define quadTabMaxBits STATNAME(quadTabMaxBits) 123 | 124 | /* map these to the corresponding 2-bit values in the frame header */ 125 | typedef enum { 126 | Stereo = 0x00, /* two independent channels, but L and R frames might have different # of bits */ 127 | Joint = 0x01, /* coupled channels - layer III: mix of M-S and intensity, Layers I/II: intensity and direct coding only */ 128 | Dual = 0x02, /* two independent channels, L and R always have exactly 1/2 the total bitrate */ 129 | Mono = 0x03 /* one channel */ 130 | } StereoMode; 131 | 132 | typedef struct _BitStreamInfo { 133 | unsigned char *bytePtr; 134 | unsigned int iCache; 135 | int cachedBits; 136 | int nBytes; 137 | } BitStreamInfo; 138 | 139 | typedef struct _FrameHeader { 140 | MPEGVersion ver; /* version ID */ 141 | int layer; /* layer index (1, 2, or 3) */ 142 | int crc; /* CRC flag: 0 = disabled, 1 = enabled */ 143 | int brIdx; /* bitrate index (0 - 15) */ 144 | int srIdx; /* sample rate index (0 - 2) */ 145 | int paddingBit; /* padding flag: 0 = no padding, 1 = single pad byte */ 146 | int privateBit; /* unused */ 147 | StereoMode sMode; /* mono/stereo mode */ 148 | int modeExt; /* used to decipher joint stereo mode */ 149 | int copyFlag; /* copyright flag: 0 = no, 1 = yes */ 150 | int origFlag; /* original flag: 0 = copy, 1 = original */ 151 | int emphasis; /* deemphasis mode */ 152 | int CRCWord; /* CRC word (16 bits, 0 if crc not enabled) */ 153 | 154 | const SFBandTable *sfBand; 155 | } FrameHeader; 156 | 157 | typedef struct _SideInfoSub { 158 | int part23Length; /* number of bits in main data */ 159 | int nBigvals; /* 2x this = first set of Huffman cw's (maximum amplitude can be > 1) */ 160 | int globalGain; /* overall gain for dequantizer */ 161 | int sfCompress; /* unpacked to figure out number of bits in scale factors */ 162 | int winSwitchFlag; /* window switching flag */ 163 | int blockType; /* block type */ 164 | int mixedBlock; /* 0 = regular block (all short or long), 1 = mixed block */ 165 | int tableSelect[3]; /* index of Huffman tables for the big values regions */ 166 | int subBlockGain[3]; /* subblock gain offset, relative to global gain */ 167 | int region0Count; /* 1+region0Count = num scale factor bands in first region of bigvals */ 168 | int region1Count; /* 1+region1Count = num scale factor bands in second region of bigvals */ 169 | int preFlag; /* for optional high frequency boost */ 170 | int sfactScale; /* scaling of the scalefactors */ 171 | int count1TableSelect; /* index of Huffman table for quad codewords */ 172 | } SideInfoSub; 173 | 174 | typedef struct _SideInfo { 175 | int mainDataBegin; 176 | int privateBits; 177 | int scfsi[MAX_NCHAN][MAX_SCFBD]; /* 4 scalefactor bands per channel */ 178 | 179 | SideInfoSub sis[MAX_NGRAN][MAX_NCHAN]; 180 | } SideInfo; 181 | 182 | typedef struct { 183 | int cbType; /* pure long = 0, pure short = 1, mixed = 2 */ 184 | int cbEndS[3]; /* number nonzero short cb's, per subbblock */ 185 | int cbEndSMax; /* max of cbEndS[] */ 186 | int cbEndL; /* number nonzero long cb's */ 187 | } CriticalBandInfo; 188 | 189 | typedef struct _DequantInfo { 190 | int workBuf[MAX_REORDER_SAMPS]; /* workbuf for reordering short blocks */ 191 | CriticalBandInfo cbi[MAX_NCHAN]; /* filled in dequantizer, used in joint stereo reconstruction */ 192 | } DequantInfo; 193 | 194 | typedef struct _HuffmanInfo { 195 | int huffDecBuf[MAX_NCHAN][MAX_NSAMP]; /* used both for decoded Huffman values and dequantized coefficients */ 196 | int nonZeroBound[MAX_NCHAN]; /* number of coeffs in huffDecBuf[ch] which can be > 0 */ 197 | int gb[MAX_NCHAN]; /* minimum number of guard bits in huffDecBuf[ch] */ 198 | } HuffmanInfo; 199 | 200 | typedef enum _HuffTabType { 201 | noBits, 202 | oneShot, 203 | loopNoLinbits, 204 | loopLinbits, 205 | quadA, 206 | quadB, 207 | invalidTab 208 | } HuffTabType; 209 | 210 | typedef struct _HuffTabLookup { 211 | int linBits; 212 | HuffTabType tabType; 213 | } HuffTabLookup; 214 | 215 | typedef struct _IMDCTInfo { 216 | int outBuf[MAX_NCHAN][BLOCK_SIZE][NBANDS]; /* output of IMDCT */ 217 | int overBuf[MAX_NCHAN][MAX_NSAMP / 2]; /* overlap-add buffer (by symmetry, only need 1/2 size) */ 218 | int numPrevIMDCT[MAX_NCHAN]; /* how many IMDCT's calculated in this channel on prev. granule */ 219 | int prevType[MAX_NCHAN]; 220 | int prevWinSwitch[MAX_NCHAN]; 221 | int gb[MAX_NCHAN]; 222 | } IMDCTInfo; 223 | 224 | typedef struct _BlockCount { 225 | int nBlocksLong; 226 | int nBlocksTotal; 227 | int nBlocksPrev; 228 | int prevType; 229 | int prevWinSwitch; 230 | int currWinSwitch; 231 | int gbIn; 232 | int gbOut; 233 | } BlockCount; 234 | 235 | /* max bits in scalefactors = 5, so use char's to save space */ 236 | typedef struct _ScaleFactorInfoSub { 237 | char l[23]; /* [band] */ 238 | char s[13][3]; /* [band][window] */ 239 | } ScaleFactorInfoSub; 240 | 241 | /* used in MPEG 2, 2.5 intensity (joint) stereo only */ 242 | typedef struct _ScaleFactorJS { 243 | int intensityScale; 244 | int slen[4]; 245 | int nr[4]; 246 | } ScaleFactorJS; 247 | 248 | typedef struct _ScaleFactorInfo { 249 | ScaleFactorInfoSub sfis[MAX_NGRAN][MAX_NCHAN]; 250 | ScaleFactorJS sfjs; 251 | } ScaleFactorInfo; 252 | 253 | /* NOTE - could get by with smaller vbuf if memory is more important than speed 254 | * (in Subband, instead of replicating each block in FDCT32 you would do a memmove on the 255 | * last 15 blocks to shift them down one, a hardware style FIFO) 256 | */ 257 | typedef struct _SubbandInfo { 258 | int vbuf[MAX_NCHAN * VBUF_LENGTH]; /* vbuf for fast DCT-based synthesis PQMF - double size for speed (no modulo indexing) */ 259 | int vindex; /* internal index for tracking position in vbuf */ 260 | } SubbandInfo; 261 | 262 | /* bitstream.c */ 263 | void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf); 264 | unsigned int GetBits(BitStreamInfo *bsi, int nBits); 265 | int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset); 266 | 267 | /* dequant.c, dqchan.c, stproc.c */ 268 | int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, FrameHeader *fh, SideInfoSub *sis, 269 | ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi); 270 | void MidSideProc(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, int mOut[2]); 271 | void IntensityProcMPEG1(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, 272 | CriticalBandInfo *cbi, int midSideFlag, int mixFlag, int mOut[2]); 273 | void IntensityProcMPEG2(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, 274 | CriticalBandInfo *cbi, ScaleFactorJS *sfjs, int midSideFlag, int mixFlag, int mOut[2]); 275 | 276 | /* dct32.c */ 277 | // about 1 ms faster in RAM, but very large 278 | void FDCT32(int *x, int *d, int offset, int oddBlock, int gb);// __attribute__ ((section (".data"))); 279 | 280 | /* hufftabs.c */ 281 | extern const HuffTabLookup huffTabLookup[HUFF_PAIRTABS]; 282 | extern const int huffTabOffset[HUFF_PAIRTABS]; 283 | extern const unsigned short huffTable[]; 284 | extern const unsigned char quadTable[64+16]; 285 | extern const int quadTabOffset[2]; 286 | extern const int quadTabMaxBits[2]; 287 | 288 | /* polyphase.c (or asmpoly.s) 289 | * some platforms require a C++ compile of all source files, 290 | * so if we're compiling C as C++ and using native assembly 291 | * for these functions we need to prevent C++ name mangling. 292 | */ 293 | #ifdef __cplusplus 294 | extern "C" { 295 | #endif 296 | void PolyphaseMono(short *pcm, int *vbuf, const int *coefBase); 297 | void PolyphaseStereo(short *pcm, int *vbuf, const int *coefBase); 298 | #ifdef __cplusplus 299 | } 300 | #endif 301 | 302 | /* trigtabs.c */ 303 | extern const int imdctWin[4][36]; 304 | extern const int ISFMpeg1[2][7]; 305 | extern const int ISFMpeg2[2][2][16]; 306 | extern const int ISFIIP[2][2]; 307 | extern const int csa[8][2]; 308 | extern const int coef32[31]; 309 | extern const int polyCoef[264]; 310 | 311 | #ifdef __cplusplus 312 | } 313 | #endif 314 | #endif /* _CODER_H */ 315 | -------------------------------------------------------------------------------- /src/dct32.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * dct32.c - optimized implementations of 32-point DCT for matrixing stage of 42 | * polyphase filter 43 | **************************************************************************************/ 44 | 45 | #include "coder.h" 46 | #include "assembly.h" 47 | 48 | #define COS0_0 0x4013c251 /* Q31 */ 49 | #define COS0_1 0x40b345bd /* Q31 */ 50 | #define COS0_2 0x41fa2d6d /* Q31 */ 51 | #define COS0_3 0x43f93421 /* Q31 */ 52 | #define COS0_4 0x46cc1bc4 /* Q31 */ 53 | #define COS0_5 0x4a9d9cf0 /* Q31 */ 54 | #define COS0_6 0x4fae3711 /* Q31 */ 55 | #define COS0_7 0x56601ea7 /* Q31 */ 56 | #define COS0_8 0x5f4cf6eb /* Q31 */ 57 | #define COS0_9 0x6b6fcf26 /* Q31 */ 58 | #define COS0_10 0x7c7d1db3 /* Q31 */ 59 | #define COS0_11 0x4ad81a97 /* Q30 */ 60 | #define COS0_12 0x5efc8d96 /* Q30 */ 61 | #define COS0_13 0x41d95790 /* Q29 */ 62 | #define COS0_14 0x6d0b20cf /* Q29 */ 63 | #define COS0_15 0x518522fb /* Q27 */ 64 | 65 | #define COS1_0 0x404f4672 /* Q31 */ 66 | #define COS1_1 0x42e13c10 /* Q31 */ 67 | #define COS1_2 0x48919f44 /* Q31 */ 68 | #define COS1_3 0x52cb0e63 /* Q31 */ 69 | #define COS1_4 0x64e2402e /* Q31 */ 70 | #define COS1_5 0x43e224a9 /* Q30 */ 71 | #define COS1_6 0x6e3c92c1 /* Q30 */ 72 | #define COS1_7 0x519e4e04 /* Q28 */ 73 | 74 | #define COS2_0 0x4140fb46 /* Q31 */ 75 | #define COS2_1 0x4cf8de88 /* Q31 */ 76 | #define COS2_2 0x73326bbf /* Q31 */ 77 | #define COS2_3 0x52036742 /* Q29 */ 78 | 79 | #define COS3_0 0x4545e9ef /* Q31 */ 80 | #define COS3_1 0x539eba45 /* Q30 */ 81 | 82 | #define COS4_0 0x5a82799a /* Q31 */ 83 | 84 | // faster in ROM 85 | static const int dcttab[48] = { 86 | /* first pass */ 87 | COS0_0, COS0_15, COS1_0, /* 31, 27, 31 */ 88 | COS0_1, COS0_14, COS1_1, /* 31, 29, 31 */ 89 | COS0_2, COS0_13, COS1_2, /* 31, 29, 31 */ 90 | COS0_3, COS0_12, COS1_3, /* 31, 30, 31 */ 91 | COS0_4, COS0_11, COS1_4, /* 31, 30, 31 */ 92 | COS0_5, COS0_10, COS1_5, /* 31, 31, 30 */ 93 | COS0_6, COS0_9, COS1_6, /* 31, 31, 30 */ 94 | COS0_7, COS0_8, COS1_7, /* 31, 31, 28 */ 95 | /* second pass */ 96 | COS2_0, COS2_3, COS3_0, /* 31, 29, 31 */ 97 | COS2_1, COS2_2, COS3_1, /* 31, 31, 30 */ 98 | -COS2_0, -COS2_3, COS3_0, /* 31, 29, 31 */ 99 | -COS2_1, -COS2_2, COS3_1, /* 31, 31, 30 */ 100 | COS2_0, COS2_3, COS3_0, /* 31, 29, 31 */ 101 | COS2_1, COS2_2, COS3_1, /* 31, 31, 30 */ 102 | -COS2_0, -COS2_3, COS3_0, /* 31, 29, 31 */ 103 | -COS2_1, -COS2_2, COS3_1, /* 31, 31, 30 */ 104 | }; 105 | 106 | #define D32FP(i, s0, s1, s2) { \ 107 | a0 = buf[i]; a3 = buf[31-i]; \ 108 | a1 = buf[15-i]; a2 = buf[16+i]; \ 109 | b0 = a0 + a3; b3 = MULSHIFT32(*cptr++, a0 - a3) << (s0); \ 110 | b1 = a1 + a2; b2 = MULSHIFT32(*cptr++, a1 - a2) << (s1); \ 111 | buf[i] = b0 + b1; buf[15-i] = MULSHIFT32(*cptr, b0 - b1) << (s2); \ 112 | buf[16+i] = b2 + b3; buf[31-i] = MULSHIFT32(*cptr++, b3 - b2) << (s2); \ 113 | } 114 | 115 | /************************************************************************************** 116 | * Function: FDCT32 117 | * 118 | * Description: Ken's highly-optimized 32-point DCT (radix-4 + radix-8) 119 | * 120 | * Inputs: input buffer, length = 32 samples 121 | * require at least 6 guard bits in input vector x to avoid possibility 122 | * of overflow in internal calculations (see bbtest_imdct test app) 123 | * buffer offset and oddblock flag for polyphase filter input buffer 124 | * number of guard bits in input 125 | * 126 | * Outputs: output buffer, data copied and interleaved for polyphase filter 127 | * no guarantees about number of guard bits in output 128 | * 129 | * Return: none 130 | * 131 | * Notes: number of muls = 4*8 + 12*4 = 80 132 | * final stage of DCT is hardcoded to shuffle data into the proper order 133 | * for the polyphase filterbank 134 | * fully unrolled stage 1, for max precision (scale the 1/cos() factors 135 | * differently, depending on magnitude) 136 | * guard bit analysis verified by exhaustive testing of all 2^32 137 | * combinations of max pos/max neg values in x[] 138 | * 139 | * TODO: code organization and optimization for ARM 140 | * possibly interleave stereo (cut # of coef loads in half - may not have 141 | * enough registers) 142 | **************************************************************************************/ 143 | // about 1ms faster in RAM 144 | /*__attribute__ ((section (".data")))*/ void FDCT32(int *buf, int *dest, int offset, int oddBlock, int gb) 145 | { 146 | int i, s, tmp, es; 147 | const int *cptr = dcttab; 148 | int a0, a1, a2, a3, a4, a5, a6, a7; 149 | int b0, b1, b2, b3, b4, b5, b6, b7; 150 | int *d; 151 | 152 | /* scaling - ensure at least 6 guard bits for DCT 153 | * (in practice this is already true 99% of time, so this code is 154 | * almost never triggered) 155 | */ 156 | es = 0; 157 | if (gb < 6) { 158 | es = 6 - gb; 159 | for (i = 0; i < 32; i++) 160 | buf[i] >>= es; 161 | } 162 | 163 | /* first pass */ 164 | D32FP(0, 1, 5, 1); 165 | D32FP(1, 1, 3, 1); 166 | D32FP(2, 1, 3, 1); 167 | D32FP(3, 1, 2, 1); 168 | D32FP(4, 1, 2, 1); 169 | D32FP(5, 1, 1, 2); 170 | D32FP(6, 1, 1, 2); 171 | D32FP(7, 1, 1, 4); 172 | 173 | /* second pass */ 174 | for (i = 4; i > 0; i--) { 175 | a0 = buf[0]; a7 = buf[7]; a3 = buf[3]; a4 = buf[4]; 176 | b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; 177 | b3 = a3 + a4; b4 = MULSHIFT32(*cptr++, a3 - a4) << 3; 178 | a0 = b0 + b3; a3 = MULSHIFT32(*cptr, b0 - b3) << 1; 179 | a4 = b4 + b7; a7 = MULSHIFT32(*cptr++, b7 - b4) << 1; 180 | 181 | a1 = buf[1]; a6 = buf[6]; a2 = buf[2]; a5 = buf[5]; 182 | b1 = a1 + a6; b6 = MULSHIFT32(*cptr++, a1 - a6) << 1; 183 | b2 = a2 + a5; b5 = MULSHIFT32(*cptr++, a2 - a5) << 1; 184 | a1 = b1 + b2; a2 = MULSHIFT32(*cptr, b1 - b2) << 2; 185 | a5 = b5 + b6; a6 = MULSHIFT32(*cptr++, b6 - b5) << 2; 186 | 187 | b0 = a0 + a1; b1 = MULSHIFT32(COS4_0, a0 - a1) << 1; 188 | b2 = a2 + a3; b3 = MULSHIFT32(COS4_0, a3 - a2) << 1; 189 | buf[0] = b0; buf[1] = b1; 190 | buf[2] = b2 + b3; buf[3] = b3; 191 | 192 | b4 = a4 + a5; b5 = MULSHIFT32(COS4_0, a4 - a5) << 1; 193 | b6 = a6 + a7; b7 = MULSHIFT32(COS4_0, a7 - a6) << 1; 194 | b6 += b7; 195 | buf[4] = b4 + b6; buf[5] = b5 + b7; 196 | buf[6] = b5 + b6; buf[7] = b7; 197 | 198 | buf += 8; 199 | } 200 | buf -= 32; /* reset */ 201 | 202 | /* sample 0 - always delayed one block */ 203 | d = dest + 64*16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH); 204 | s = buf[ 0]; d[0] = d[8] = s; 205 | 206 | /* samples 16 to 31 */ 207 | d = dest + offset + (oddBlock ? VBUF_LENGTH : 0); 208 | 209 | s = buf[ 1]; d[0] = d[8] = s; d += 64; 210 | 211 | tmp = buf[25] + buf[29]; 212 | s = buf[17] + tmp; d[0] = d[8] = s; d += 64; 213 | s = buf[ 9] + buf[13]; d[0] = d[8] = s; d += 64; 214 | s = buf[21] + tmp; d[0] = d[8] = s; d += 64; 215 | 216 | tmp = buf[29] + buf[27]; 217 | s = buf[ 5]; d[0] = d[8] = s; d += 64; 218 | s = buf[21] + tmp; d[0] = d[8] = s; d += 64; 219 | s = buf[13] + buf[11]; d[0] = d[8] = s; d += 64; 220 | s = buf[19] + tmp; d[0] = d[8] = s; d += 64; 221 | 222 | tmp = buf[27] + buf[31]; 223 | s = buf[ 3]; d[0] = d[8] = s; d += 64; 224 | s = buf[19] + tmp; d[0] = d[8] = s; d += 64; 225 | s = buf[11] + buf[15]; d[0] = d[8] = s; d += 64; 226 | s = buf[23] + tmp; d[0] = d[8] = s; d += 64; 227 | 228 | tmp = buf[31]; 229 | s = buf[ 7]; d[0] = d[8] = s; d += 64; 230 | s = buf[23] + tmp; d[0] = d[8] = s; d += 64; 231 | s = buf[15]; d[0] = d[8] = s; d += 64; 232 | s = tmp; d[0] = d[8] = s; 233 | 234 | /* samples 16 to 1 (sample 16 used again) */ 235 | d = dest + 16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH); 236 | 237 | s = buf[ 1]; d[0] = d[8] = s; d += 64; 238 | 239 | tmp = buf[30] + buf[25]; 240 | s = buf[17] + tmp; d[0] = d[8] = s; d += 64; 241 | s = buf[14] + buf[ 9]; d[0] = d[8] = s; d += 64; 242 | s = buf[22] + tmp; d[0] = d[8] = s; d += 64; 243 | s = buf[ 6]; d[0] = d[8] = s; d += 64; 244 | 245 | tmp = buf[26] + buf[30]; 246 | s = buf[22] + tmp; d[0] = d[8] = s; d += 64; 247 | s = buf[10] + buf[14]; d[0] = d[8] = s; d += 64; 248 | s = buf[18] + tmp; d[0] = d[8] = s; d += 64; 249 | s = buf[ 2]; d[0] = d[8] = s; d += 64; 250 | 251 | tmp = buf[28] + buf[26]; 252 | s = buf[18] + tmp; d[0] = d[8] = s; d += 64; 253 | s = buf[12] + buf[10]; d[0] = d[8] = s; d += 64; 254 | s = buf[20] + tmp; d[0] = d[8] = s; d += 64; 255 | s = buf[ 4]; d[0] = d[8] = s; d += 64; 256 | 257 | tmp = buf[24] + buf[28]; 258 | s = buf[20] + tmp; d[0] = d[8] = s; d += 64; 259 | s = buf[ 8] + buf[12]; d[0] = d[8] = s; d += 64; 260 | s = buf[16] + tmp; d[0] = d[8] = s; 261 | 262 | /* this is so rarely invoked that it's not worth making two versions of the output 263 | * shuffle code (one for no shift, one for clip + variable shift) like in IMDCT 264 | * here we just load, clip, shift, and store on the rare instances that es != 0 265 | */ 266 | if (es) { 267 | d = dest + 64*16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH); 268 | s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es); 269 | 270 | d = dest + offset + (oddBlock ? VBUF_LENGTH : 0); 271 | for (i = 16; i <= 31; i++) { 272 | s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es); d += 64; 273 | } 274 | 275 | d = dest + 16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH); 276 | for (i = 15; i >= 0; i--) { 277 | s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es); d += 64; 278 | } 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /src/dequant.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * dequant.c - dequantization, stereo processing (intensity, mid-side), short-block 42 | * coefficient reordering 43 | **************************************************************************************/ 44 | 45 | #include "coder.h" 46 | #include "assembly.h" 47 | 48 | /************************************************************************************** 49 | * Function: Dequantize 50 | * 51 | * Description: dequantize coefficients, decode stereo, reorder short blocks 52 | * (one granule-worth) 53 | * 54 | * Inputs: MP3DecInfo structure filled by UnpackFrameHeader(), UnpackSideInfo(), 55 | * UnpackScaleFactors(), and DecodeHuffman() (for this granule) 56 | * index of current granule 57 | * 58 | * Outputs: dequantized and reordered coefficients in hi->huffDecBuf 59 | * (one granule-worth, all channels), format = Q26 60 | * operates in-place on huffDecBuf but also needs di->workBuf 61 | * updated hi->nonZeroBound index for both channels 62 | * 63 | * Return: 0 on success, -1 if null input pointers 64 | * 65 | * Notes: In calling output Q(DQ_FRACBITS_OUT), we assume an implicit bias 66 | * of 2^15. Some (floating-point) reference implementations factor this 67 | * into the 2^(0.25 * gain) scaling explicitly. But to avoid precision 68 | * loss, we don't do that. Instead take it into account in the final 69 | * round to PCM (>> by 15 less than we otherwise would have). 70 | * Equivalently, we can think of the dequantized coefficients as 71 | * Q(DQ_FRACBITS_OUT - 15) with no implicit bias. 72 | **************************************************************************************/ 73 | int Dequantize(MP3DecInfo *mp3DecInfo, int gr) 74 | { 75 | int i, ch, nSamps, mOut[2]; 76 | FrameHeader *fh; 77 | SideInfo *si; 78 | ScaleFactorInfo *sfi; 79 | HuffmanInfo *hi; 80 | DequantInfo *di; 81 | CriticalBandInfo *cbi; 82 | 83 | /* validate pointers */ 84 | if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS || 85 | !mp3DecInfo->HuffmanInfoPS || !mp3DecInfo->DequantInfoPS) 86 | return -1; 87 | 88 | fh = (FrameHeader *)(mp3DecInfo->FrameHeaderPS); 89 | 90 | /* si is an array of up to 4 structs, stored as gr0ch0, gr0ch1, gr1ch0, gr1ch1 */ 91 | si = (SideInfo *)(mp3DecInfo->SideInfoPS); 92 | sfi = (ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS); 93 | hi = (HuffmanInfo *)mp3DecInfo->HuffmanInfoPS; 94 | di = (DequantInfo *)mp3DecInfo->DequantInfoPS; 95 | cbi = di->cbi; 96 | mOut[0] = mOut[1] = 0; 97 | 98 | /* dequantize all the samples in each channel */ 99 | for (ch = 0; ch < mp3DecInfo->nChans; ch++) { 100 | hi->gb[ch] = DequantChannel(hi->huffDecBuf[ch], di->workBuf, &hi->nonZeroBound[ch], fh, 101 | &si->sis[gr][ch], &sfi->sfis[gr][ch], &cbi[ch]); 102 | } 103 | 104 | /* joint stereo processing assumes one guard bit in input samples 105 | * it's extremely rare not to have at least one gb, so if this is the case 106 | * just make a pass over the data and clip to [-2^30+1, 2^30-1] 107 | * in practice this may never happen 108 | */ 109 | if (fh->modeExt && (hi->gb[0] < 1 || hi->gb[1] < 1)) { 110 | for (i = 0; i < hi->nonZeroBound[0]; i++) { 111 | if (hi->huffDecBuf[0][i] < -0x3fffffff) hi->huffDecBuf[0][i] = -0x3fffffff; 112 | if (hi->huffDecBuf[0][i] > 0x3fffffff) hi->huffDecBuf[0][i] = 0x3fffffff; 113 | } 114 | for (i = 0; i < hi->nonZeroBound[1]; i++) { 115 | if (hi->huffDecBuf[1][i] < -0x3fffffff) hi->huffDecBuf[1][i] = -0x3fffffff; 116 | if (hi->huffDecBuf[1][i] > 0x3fffffff) hi->huffDecBuf[1][i] = 0x3fffffff; 117 | } 118 | } 119 | 120 | /* do mid-side stereo processing, if enabled */ 121 | if (fh->modeExt >> 1) { 122 | if (fh->modeExt & 0x01) { 123 | /* intensity stereo enabled - run mid-side up to start of right zero region */ 124 | if (cbi[1].cbType == 0) 125 | nSamps = fh->sfBand->l[cbi[1].cbEndL + 1]; 126 | else 127 | nSamps = 3 * fh->sfBand->s[cbi[1].cbEndSMax + 1]; 128 | } else { 129 | /* intensity stereo disabled - run mid-side on whole spectrum */ 130 | nSamps = MAX(hi->nonZeroBound[0], hi->nonZeroBound[1]); 131 | } 132 | MidSideProc(hi->huffDecBuf, nSamps, mOut); 133 | } 134 | 135 | /* do intensity stereo processing, if enabled */ 136 | if (fh->modeExt & 0x01) { 137 | nSamps = hi->nonZeroBound[0]; 138 | if (fh->ver == MPEG1) { 139 | IntensityProcMPEG1(hi->huffDecBuf, nSamps, fh, &sfi->sfis[gr][1], di->cbi, 140 | fh->modeExt >> 1, si->sis[gr][1].mixedBlock, mOut); 141 | } else { 142 | IntensityProcMPEG2(hi->huffDecBuf, nSamps, fh, &sfi->sfis[gr][1], di->cbi, &sfi->sfjs, 143 | fh->modeExt >> 1, si->sis[gr][1].mixedBlock, mOut); 144 | } 145 | } 146 | 147 | /* adjust guard bit count and nonZeroBound if we did any stereo processing */ 148 | if (fh->modeExt) { 149 | hi->gb[0] = CLZ(mOut[0]) - 1; 150 | hi->gb[1] = CLZ(mOut[1]) - 1; 151 | nSamps = MAX(hi->nonZeroBound[0], hi->nonZeroBound[1]); 152 | hi->nonZeroBound[0] = nSamps; 153 | hi->nonZeroBound[1] = nSamps; 154 | } 155 | 156 | /* output format Q(DQ_FRACBITS_OUT) */ 157 | return 0; 158 | } 159 | -------------------------------------------------------------------------------- /src/dqchan.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * August 2003 40 | * 41 | * dqchan.c - dequantization of transform coefficients 42 | **************************************************************************************/ 43 | 44 | #include "coder.h" 45 | #include "assembly.h" 46 | #include 47 | 48 | typedef int ARRAY3[3]; /* for short-block reordering */ 49 | 50 | /* optional pre-emphasis for high-frequency scale factor bands */ 51 | static const char preTab[22] = { 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0 }; 52 | 53 | /* pow(2,-i/4) for i=0..3, Q31 format */ 54 | static const int pow14[4] = { 55 | 0x7fffffff, 0x6ba27e65, 0x5a82799a, 0x4c1bf829 56 | }; 57 | 58 | /* pow(2,-i/4) * pow(j,4/3) for i=0..3 j=0..15, Q25 format */ 59 | static const int pow43_14[4][16] = { 60 | { 0x00000000, 0x10000000, 0x285145f3, 0x453a5cdb, /* Q28 */ 61 | 0x0cb2ff53, 0x111989d6, 0x15ce31c8, 0x1ac7f203, 62 | 0x20000000, 0x257106b9, 0x2b16b4a3, 0x30ed74b4, 63 | 0x36f23fa5, 0x3d227bd3, 0x437be656, 0x49fc823c, }, 64 | 65 | { 0x00000000, 0x0d744fcd, 0x21e71f26, 0x3a36abd9, 66 | 0x0aadc084, 0x0e610e6e, 0x12560c1d, 0x168523cf, 67 | 0x1ae89f99, 0x1f7c03a4, 0x243bae49, 0x29249c67, 68 | 0x2e34420f, 0x33686f85, 0x38bf3dff, 0x3e370182, }, 69 | 70 | { 0x00000000, 0x0b504f33, 0x1c823e07, 0x30f39a55, 71 | 0x08facd62, 0x0c176319, 0x0f6b3522, 0x12efe2ad, 72 | 0x16a09e66, 0x1a79a317, 0x1e77e301, 0x2298d5b4, 73 | 0x26da56fc, 0x2b3a902a, 0x2fb7e7e7, 0x3450f650, }, 74 | 75 | { 0x00000000, 0x09837f05, 0x17f910d7, 0x2929c7a9, 76 | 0x078d0dfa, 0x0a2ae661, 0x0cf73154, 0x0fec91cb, 77 | 0x1306fe0a, 0x16434a6c, 0x199ee595, 0x1d17ae3d, 78 | 0x20abd76a, 0x2459d551, 0x28204fbb, 0x2bfe1808, }, 79 | }; 80 | 81 | /* pow(j,4/3) for j=16..63, Q23 format */ 82 | static const int pow43[] = { 83 | 0x1428a2fa, 0x15db1bd6, 0x1796302c, 0x19598d85, 84 | 0x1b24e8bb, 0x1cf7fcfa, 0x1ed28af2, 0x20b4582a, 85 | 0x229d2e6e, 0x248cdb55, 0x26832fda, 0x28800000, 86 | 0x2a832287, 0x2c8c70a8, 0x2e9bc5d8, 0x30b0ff99, 87 | 0x32cbfd4a, 0x34eca001, 0x3712ca62, 0x393e6088, 88 | 0x3b6f47e0, 0x3da56717, 0x3fe0a5fc, 0x4220ed72, 89 | 0x44662758, 0x46b03e7c, 0x48ff1e87, 0x4b52b3f3, 90 | 0x4daaebfd, 0x5007b497, 0x5268fc62, 0x54ceb29c, 91 | 0x5738c721, 0x59a72a59, 0x5c19cd35, 0x5e90a129, 92 | 0x610b9821, 0x638aa47f, 0x660db90f, 0x6894c90b, 93 | 0x6b1fc80c, 0x6daeaa0d, 0x70416360, 0x72d7e8b0, 94 | 0x75722ef9, 0x78102b85, 0x7ab1d3ec, 0x7d571e09, 95 | }; 96 | 97 | /* sqrt(0.5) in Q31 format */ 98 | #define SQRTHALF 0x5a82799a 99 | 100 | /* 101 | * Minimax polynomial approximation to pow(x, 4/3), over the range 102 | * poly43lo: x = [0.5, 0.7071] 103 | * poly43hi: x = [0.7071, 1.0] 104 | * 105 | * Relative error < 1E-7 106 | * Coefs are scaled by 4, 2, 1, 0.5, 0.25 107 | */ 108 | static const int poly43lo[5] = { (int32_t)0x29a0bda9, (int32_t)0xb02e4828, (int32_t)0x5957aa1b, (int32_t)0x236c498d, (int32_t)0xff581859 }; 109 | static const int poly43hi[5] = { (int32_t)0x10852163, (int32_t)0xd333f6a4, (int32_t)0x46e9408b, (int32_t)0x27c2cef0, (int32_t)0xfef577b4 }; 110 | 111 | /* pow(2, i*4/3) as exp and frac */ 112 | static const int pow2exp[8] = { 14, 13, 11, 10, 9, 7, 6, 5 }; 113 | 114 | static const int pow2frac[8] = { 115 | 0x6597fa94, 0x50a28be6, 0x7fffffff, 0x6597fa94, 116 | 0x50a28be6, 0x7fffffff, 0x6597fa94, 0x50a28be6 117 | }; 118 | 119 | /************************************************************************************** 120 | * Function: DequantBlock 121 | * 122 | * Description: Ken's highly-optimized, low memory dequantizer performing the operation 123 | * y = pow(x, 4.0/3.0) * pow(2, 25 - scale/4.0) 124 | * 125 | * Inputs: input buffer of decode Huffman codewords (signed-magnitude) 126 | * output buffer of same length (in-place (outbuf = inbuf) is allowed) 127 | * number of samples 128 | * 129 | * Outputs: dequantized samples in Q25 format 130 | * 131 | * Return: bitwise-OR of the unsigned outputs (for guard bit calculations) 132 | **************************************************************************************/ 133 | /*__attribute__ ((section (".data")))*/ static int DequantBlock(int *inbuf, int *outbuf, int num, int scale) 134 | { 135 | int tab4[4]; 136 | int scalef, scalei, shift; 137 | int sx, x, y; 138 | int mask = 0; 139 | const int *tab16, *coef; 140 | 141 | tab16 = pow43_14[scale & 0x3]; 142 | scalef = pow14[scale & 0x3]; 143 | scalei = MIN(scale >> 2, 31); /* smallest input scale = -47, so smallest scalei = -12 */ 144 | 145 | /* cache first 4 values */ 146 | shift = MIN(scalei + 3, 31); 147 | shift = MAX(shift, 0); 148 | tab4[0] = 0; 149 | tab4[1] = tab16[1] >> shift; 150 | tab4[2] = tab16[2] >> shift; 151 | tab4[3] = tab16[3] >> shift; 152 | 153 | do { 154 | 155 | sx = *inbuf++; 156 | x = sx & 0x7fffffff; /* sx = sign|mag */ 157 | 158 | if (x < 4) { 159 | 160 | y = tab4[x]; 161 | 162 | } else if (x < 16) { 163 | 164 | y = tab16[x]; 165 | y = (scalei < 0) ? y << -scalei : y >> scalei; 166 | 167 | } else { 168 | 169 | if (x < 64) { 170 | 171 | y = pow43[x-16]; 172 | 173 | /* fractional scale */ 174 | y = MULSHIFT32(y, scalef); 175 | shift = scalei - 3; 176 | 177 | } else { 178 | 179 | /* normalize to [0x40000000, 0x7fffffff] */ 180 | x <<= 17; 181 | shift = 0; 182 | if (x < 0x08000000) 183 | x <<= 4, shift += 4; 184 | if (x < 0x20000000) 185 | x <<= 2, shift += 2; 186 | if (x < 0x40000000) 187 | x <<= 1, shift += 1; 188 | 189 | coef = (x < SQRTHALF) ? poly43lo : poly43hi; 190 | 191 | /* polynomial */ 192 | y = coef[0]; 193 | y = MULSHIFT32(y, x) + coef[1]; 194 | y = MULSHIFT32(y, x) + coef[2]; 195 | y = MULSHIFT32(y, x) + coef[3]; 196 | y = MULSHIFT32(y, x) + coef[4]; 197 | y = MULSHIFT32(y, pow2frac[shift]) << 3; 198 | 199 | /* fractional scale */ 200 | y = MULSHIFT32(y, scalef); 201 | shift = scalei - pow2exp[shift]; 202 | } 203 | 204 | /* integer scale */ 205 | if (shift < 0) { 206 | shift = -shift; 207 | if (y > (0x7fffffff >> shift)) 208 | y = 0x7fffffff; /* clip */ 209 | else 210 | y <<= shift; 211 | } else { 212 | y >>= shift; 213 | } 214 | } 215 | 216 | /* sign and store */ 217 | mask |= y; 218 | *outbuf++ = (sx < 0) ? -y : y; 219 | 220 | } while (--num); 221 | 222 | return mask; 223 | } 224 | 225 | /************************************************************************************** 226 | * Function: DequantChannel 227 | * 228 | * Description: dequantize one granule, one channel worth of decoded Huffman codewords 229 | * 230 | * Inputs: sample buffer (decoded Huffman codewords), length = MAX_NSAMP samples 231 | * work buffer for reordering short-block, length = MAX_REORDER_SAMPS 232 | * samples (3 * width of largest short-block critical band) 233 | * non-zero bound for this channel/granule 234 | * valid FrameHeader, SideInfoSub, ScaleFactorInfoSub, and CriticalBandInfo 235 | * structures for this channel/granule 236 | * 237 | * Outputs: MAX_NSAMP dequantized samples in sampleBuf 238 | * updated non-zero bound (indicating which samples are != 0 after DQ) 239 | * filled-in cbi structure indicating start and end critical bands 240 | * 241 | * Return: minimum number of guard bits in dequantized sampleBuf 242 | * 243 | * Notes: dequantized samples in Q(DQ_FRACBITS_OUT) format 244 | **************************************************************************************/ 245 | /*__attribute__ ((section (".data")))*/ int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, FrameHeader *fh, SideInfoSub *sis, 246 | ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi) 247 | { 248 | int i, j, w, cb; 249 | int cbEndL, cbStartS, cbEndS; 250 | int nSamps, nonZero, sfactMultiplier, gbMask; 251 | int globalGain, gainI; 252 | int cbMax[3]; 253 | ARRAY3 *buf; /* short block reorder */ 254 | 255 | /* set default start/end points for short/long blocks - will update with non-zero cb info */ 256 | if (sis->blockType == 2) { 257 | if (sis->mixedBlock) { 258 | cbEndL = (fh->ver == MPEG1 ? 8 : 6); 259 | cbStartS = 3; 260 | } else { 261 | cbEndL = 0; 262 | cbStartS = 0; 263 | } 264 | cbEndS = 13; 265 | } else { 266 | /* long block */ 267 | cbEndL = 22; 268 | cbStartS = 13; 269 | cbEndS = 13; 270 | } 271 | cbMax[2] = cbMax[1] = cbMax[0] = 0; 272 | gbMask = 0; 273 | i = 0; 274 | 275 | /* sfactScale = 0 --> quantizer step size = 2 276 | * sfactScale = 1 --> quantizer step size = sqrt(2) 277 | * so sfactMultiplier = 2 or 4 (jump through globalGain by powers of 2 or sqrt(2)) 278 | */ 279 | sfactMultiplier = 2 * (sis->sfactScale + 1); 280 | 281 | /* offset globalGain by -2 if midSide enabled, for 1/sqrt(2) used in MidSideProc() 282 | * (DequantBlock() does 0.25 * gainI so knocking it down by two is the same as 283 | * dividing every sample by sqrt(2) = multiplying by 2^-.5) 284 | */ 285 | globalGain = sis->globalGain; 286 | if (fh->modeExt >> 1) 287 | globalGain -= 2; 288 | globalGain += IMDCT_SCALE; /* scale everything by sqrt(2), for fast IMDCT36 */ 289 | 290 | /* long blocks */ 291 | for (cb = 0; cb < cbEndL; cb++) { 292 | 293 | nonZero = 0; 294 | nSamps = fh->sfBand->l[cb + 1] - fh->sfBand->l[cb]; 295 | gainI = 210 - globalGain + sfactMultiplier * (sfis->l[cb] + (sis->preFlag ? (int)preTab[cb] : 0)); 296 | 297 | nonZero |= DequantBlock(sampleBuf + i, sampleBuf + i, nSamps, gainI); 298 | i += nSamps; 299 | 300 | /* update highest non-zero critical band */ 301 | if (nonZero) 302 | cbMax[0] = cb; 303 | gbMask |= nonZero; 304 | 305 | if (i >= *nonZeroBound) 306 | break; 307 | } 308 | 309 | /* set cbi (Type, EndS[], EndSMax will be overwritten if we proceed to do short blocks) */ 310 | cbi->cbType = 0; /* long only */ 311 | cbi->cbEndL = cbMax[0]; 312 | cbi->cbEndS[0] = cbi->cbEndS[1] = cbi->cbEndS[2] = 0; 313 | cbi->cbEndSMax = 0; 314 | 315 | /* early exit if no short blocks */ 316 | if (cbStartS >= 12) 317 | return CLZ(gbMask) - 1; 318 | 319 | /* short blocks */ 320 | cbMax[2] = cbMax[1] = cbMax[0] = cbStartS; 321 | for (cb = cbStartS; cb < cbEndS; cb++) { 322 | 323 | nSamps = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb]; 324 | for (w = 0; w < 3; w++) { 325 | nonZero = 0; 326 | gainI = 210 - globalGain + 8*sis->subBlockGain[w] + sfactMultiplier*(sfis->s[cb][w]); 327 | 328 | nonZero |= DequantBlock(sampleBuf + i + nSamps*w, workBuf + nSamps*w, nSamps, gainI); 329 | 330 | /* update highest non-zero critical band */ 331 | if (nonZero) 332 | cbMax[w] = cb; 333 | gbMask |= nonZero; 334 | } 335 | 336 | /* reorder blocks */ 337 | buf = (ARRAY3 *)(sampleBuf + i); 338 | i += 3*nSamps; 339 | for (j = 0; j < nSamps; j++) { 340 | buf[j][0] = workBuf[0*nSamps + j]; 341 | buf[j][1] = workBuf[1*nSamps + j]; 342 | buf[j][2] = workBuf[2*nSamps + j]; 343 | } 344 | 345 | ASSERT(3*nSamps <= MAX_REORDER_SAMPS); 346 | 347 | if (i >= *nonZeroBound) 348 | break; 349 | } 350 | 351 | /* i = last non-zero INPUT sample processed, which corresponds to highest possible non-zero 352 | * OUTPUT sample (after reorder) 353 | * however, the original nzb is no longer necessarily true 354 | * for each cb, buf[][] is updated with 3*nSamps samples (i increases 3*nSamps each time) 355 | * (buf[j + 1][0] = 3 (input) samples ahead of buf[j][0]) 356 | * so update nonZeroBound to i 357 | */ 358 | *nonZeroBound = i; 359 | 360 | ASSERT(*nonZeroBound <= MAX_NSAMP); 361 | 362 | cbi->cbType = (sis->mixedBlock ? 2 : 1); /* 2 = mixed short/long, 1 = short only */ 363 | 364 | cbi->cbEndS[0] = cbMax[0]; 365 | cbi->cbEndS[1] = cbMax[1]; 366 | cbi->cbEndS[2] = cbMax[2]; 367 | 368 | cbi->cbEndSMax = cbMax[0]; 369 | cbi->cbEndSMax = MAX(cbi->cbEndSMax, cbMax[1]); 370 | cbi->cbEndSMax = MAX(cbi->cbEndSMax, cbMax[2]); 371 | 372 | return CLZ(gbMask) - 1; 373 | } 374 | 375 | -------------------------------------------------------------------------------- /src/mp3common.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * mp3common.h - implementation-independent API's, datatypes, and definitions 42 | **************************************************************************************/ 43 | 44 | #ifndef _MP3COMMON_H 45 | #define _MP3COMMON_H 46 | 47 | #include "mp3dec.h" 48 | #include "statname.h" /* do name-mangling for static linking */ 49 | 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | 54 | #define MAX_SCFBD 4 /* max scalefactor bands per channel */ 55 | #define NGRANS_MPEG1 2 56 | #define NGRANS_MPEG2 1 57 | 58 | /* 11-bit syncword if MPEG 2.5 extensions are enabled */ 59 | #define SYNCWORDH 0xff 60 | #define SYNCWORDL 0xe0 61 | 62 | /* 12-bit syncword if MPEG 1,2 only are supported 63 | * #define SYNCWORDH 0xff 64 | * #define SYNCWORDL 0xf0 65 | */ 66 | 67 | typedef struct _MP3DecInfo { 68 | /* pointers to platform-specific data structures */ 69 | void *FrameHeaderPS; 70 | void *SideInfoPS; 71 | void *ScaleFactorInfoPS; 72 | void *HuffmanInfoPS; 73 | void *DequantInfoPS; 74 | void *IMDCTInfoPS; 75 | void *SubbandInfoPS; 76 | 77 | /* buffer which must be large enough to hold largest possible main_data section */ 78 | unsigned char mainBuf[MAINBUF_SIZE]; 79 | 80 | /* special info for "free" bitrate files */ 81 | int freeBitrateFlag; 82 | int freeBitrateSlots; 83 | 84 | /* user-accessible info */ 85 | int bitrate; 86 | int nChans; 87 | int samprate; 88 | int nGrans; /* granules per frame */ 89 | int nGranSamps; /* samples per granule */ 90 | int nSlots; 91 | int layer; 92 | MPEGVersion version; 93 | 94 | int mainDataBegin; 95 | int mainDataBytes; 96 | 97 | int part23Length[MAX_NGRAN][MAX_NCHAN]; 98 | 99 | } MP3DecInfo; 100 | 101 | typedef struct _SFBandTable { 102 | short l[23]; 103 | short s[14]; 104 | } SFBandTable; 105 | 106 | /* decoder functions which must be implemented for each platform */ 107 | MP3DecInfo *AllocateBuffers(void); 108 | void FreeBuffers(MP3DecInfo *mp3DecInfo); 109 | int CheckPadBit(MP3DecInfo *mp3DecInfo); 110 | int UnpackFrameHeader(MP3DecInfo *mp3DecInfo, unsigned char *buf); 111 | int UnpackSideInfo(MP3DecInfo *mp3DecInfo, unsigned char *buf); 112 | int DecodeHuffman(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int huffBlockBits, int gr, int ch); 113 | int Dequantize(MP3DecInfo *mp3DecInfo, int gr); 114 | int IMDCT(MP3DecInfo *mp3DecInfo, int gr, int ch); 115 | int UnpackScaleFactors(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch); 116 | int Subband(MP3DecInfo *mp3DecInfo, short *pcmBuf); 117 | 118 | /* mp3tabs.c - global ROM tables */ 119 | extern const int samplerateTab[3][3]; 120 | extern const short bitrateTab[3][3][15]; 121 | extern const short samplesPerFrameTab[3][3]; 122 | extern const short bitsPerSlotTab[3]; 123 | extern const short sideBytesTab[3][2]; 124 | extern const short slotTab[3][3][15]; 125 | extern const SFBandTable sfBandTable[3][3]; 126 | 127 | #ifdef __cplusplus 128 | } 129 | #endif 130 | 131 | #endif /* _MP3COMMON_H */ 132 | -------------------------------------------------------------------------------- /src/mp3dec.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * mp3dec.c - platform-independent top level MP3 decoder API 42 | **************************************************************************************/ 43 | 44 | #include /* for memmove, memcpy (can replace with different implementations if desired) */ 45 | #include "mp3common.h" /* includes mp3dec.h (public API) and internal, platform-independent API */ 46 | //#include "hxthreadyield.h" 47 | 48 | /************************************************************************************** 49 | * Function: MP3InitDecoder 50 | * 51 | * Description: allocate memory for platform-specific data 52 | * clear all the user-accessible fields 53 | * 54 | * Inputs: none 55 | * 56 | * Outputs: none 57 | * 58 | * Return: handle to mp3 decoder instance, 0 if malloc fails 59 | **************************************************************************************/ 60 | HMP3Decoder MP3InitDecoder(void) 61 | { 62 | MP3DecInfo *mp3DecInfo; 63 | 64 | mp3DecInfo = AllocateBuffers(); 65 | 66 | return (HMP3Decoder)mp3DecInfo; 67 | } 68 | 69 | /************************************************************************************** 70 | * Function: MP3FreeDecoder 71 | * 72 | * Description: free platform-specific data allocated by InitMP3Decoder 73 | * zero out the contents of MP3DecInfo struct 74 | * 75 | * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) 76 | * 77 | * Outputs: none 78 | * 79 | * Return: none 80 | **************************************************************************************/ 81 | void MP3FreeDecoder(HMP3Decoder hMP3Decoder) 82 | { 83 | MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; 84 | 85 | if (!mp3DecInfo) 86 | return; 87 | 88 | FreeBuffers(mp3DecInfo); 89 | } 90 | 91 | /************************************************************************************** 92 | * Function: MP3FindSyncWord 93 | * 94 | * Description: locate the next byte-alinged sync word in the raw mp3 stream 95 | * 96 | * Inputs: buffer to search for sync word 97 | * max number of bytes to search in buffer 98 | * 99 | * Outputs: none 100 | * 101 | * Return: offset to first sync word (bytes from start of buf) 102 | * -1 if sync not found after searching nBytes 103 | **************************************************************************************/ 104 | int MP3FindSyncWord(unsigned char *buf, int nBytes) 105 | { 106 | int i; 107 | 108 | /* find byte-aligned syncword - need 12 (MPEG 1,2) or 11 (MPEG 2.5) matching bits */ 109 | for (i = 0; i < nBytes - 1; i++) { 110 | if ( (buf[i+0] & SYNCWORDH) == SYNCWORDH && (buf[i+1] & SYNCWORDL) == SYNCWORDL ) 111 | return i; 112 | } 113 | 114 | return -1; 115 | } 116 | 117 | /************************************************************************************** 118 | * Function: MP3FindFreeSync 119 | * 120 | * Description: figure out number of bytes between adjacent sync words in "free" mode 121 | * 122 | * Inputs: buffer to search for next sync word 123 | * the 4-byte frame header starting at the current sync word 124 | * max number of bytes to search in buffer 125 | * 126 | * Outputs: none 127 | * 128 | * Return: offset to next sync word, minus any pad byte (i.e. nSlots) 129 | * -1 if sync not found after searching nBytes 130 | * 131 | * Notes: this checks that the first 22 bits of the next frame header are the 132 | * same as the current frame header, but it's still not foolproof 133 | * (could accidentally find a sequence in the bitstream which 134 | * appears to match but is not actually the next frame header) 135 | * this could be made more error-resilient by checking several frames 136 | * in a row and verifying that nSlots is the same in each case 137 | * since free mode requires CBR (see spec) we generally only call 138 | * this function once (first frame) then store the result (nSlots) 139 | * and just use it from then on 140 | **************************************************************************************/ 141 | static int MP3FindFreeSync(unsigned char *buf, unsigned char firstFH[4], int nBytes) 142 | { 143 | int offset = 0; 144 | unsigned char *bufPtr = buf; 145 | 146 | /* loop until we either: 147 | * - run out of nBytes (FindMP3SyncWord() returns -1) 148 | * - find the next valid frame header (sync word, version, layer, CRC flag, bitrate, and sample rate 149 | * in next header must match current header) 150 | */ 151 | while (1) { 152 | offset = MP3FindSyncWord(bufPtr, nBytes); 153 | bufPtr += offset; 154 | if (offset < 0) { 155 | return -1; 156 | } else if ( (bufPtr[0] == firstFH[0]) && (bufPtr[1] == firstFH[1]) && ((bufPtr[2] & 0xfc) == (firstFH[2] & 0xfc)) ) { 157 | /* want to return number of bytes per frame, NOT counting the padding byte, so subtract one if padFlag == 1 */ 158 | if ((firstFH[2] >> 1) & 0x01) 159 | bufPtr--; 160 | return bufPtr - buf; 161 | } 162 | bufPtr += 3; 163 | nBytes -= (offset + 3); 164 | }; 165 | 166 | return -1; 167 | } 168 | 169 | /************************************************************************************** 170 | * Function: MP3GetLastFrameInfo 171 | * 172 | * Description: get info about last MP3 frame decoded (number of sampled decoded, 173 | * sample rate, bitrate, etc.) 174 | * 175 | * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) 176 | * pointer to MP3FrameInfo struct 177 | * 178 | * Outputs: filled-in MP3FrameInfo struct 179 | * 180 | * Return: none 181 | * 182 | * Notes: call this right after calling MP3Decode 183 | **************************************************************************************/ 184 | void MP3GetLastFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo) 185 | { 186 | MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; 187 | 188 | if (!mp3DecInfo || mp3DecInfo->layer != 3) { 189 | mp3FrameInfo->bitrate = 0; 190 | mp3FrameInfo->nChans = 0; 191 | mp3FrameInfo->samprate = 0; 192 | mp3FrameInfo->bitsPerSample = 0; 193 | mp3FrameInfo->outputSamps = 0; 194 | mp3FrameInfo->layer = 0; 195 | mp3FrameInfo->version = 0; 196 | } else { 197 | mp3FrameInfo->bitrate = mp3DecInfo->bitrate; 198 | mp3FrameInfo->nChans = mp3DecInfo->nChans; 199 | mp3FrameInfo->samprate = mp3DecInfo->samprate; 200 | mp3FrameInfo->bitsPerSample = 16; 201 | mp3FrameInfo->outputSamps = mp3DecInfo->nChans * (int)samplesPerFrameTab[mp3DecInfo->version][mp3DecInfo->layer - 1]; 202 | mp3FrameInfo->layer = mp3DecInfo->layer; 203 | mp3FrameInfo->version = mp3DecInfo->version; 204 | } 205 | } 206 | 207 | /************************************************************************************** 208 | * Function: MP3GetNextFrameInfo 209 | * 210 | * Description: parse MP3 frame header 211 | * 212 | * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) 213 | * pointer to MP3FrameInfo struct 214 | * pointer to buffer containing valid MP3 frame header (located using 215 | * MP3FindSyncWord(), above) 216 | * 217 | * Outputs: filled-in MP3FrameInfo struct 218 | * 219 | * Return: error code, defined in mp3dec.h (0 means no error, < 0 means error) 220 | **************************************************************************************/ 221 | int MP3GetNextFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo, unsigned char *buf) 222 | { 223 | MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; 224 | 225 | if (!mp3DecInfo) 226 | return ERR_MP3_NULL_POINTER; 227 | 228 | if (UnpackFrameHeader(mp3DecInfo, buf) == -1 || mp3DecInfo->layer != 3) 229 | return ERR_MP3_INVALID_FRAMEHEADER; 230 | 231 | MP3GetLastFrameInfo(mp3DecInfo, mp3FrameInfo); 232 | 233 | return ERR_MP3_NONE; 234 | } 235 | 236 | /************************************************************************************** 237 | * Function: MP3ClearBadFrame 238 | * 239 | * Description: zero out pcm buffer if error decoding MP3 frame 240 | * 241 | * Inputs: mp3DecInfo struct with correct frame size parameters filled in 242 | * pointer pcm output buffer 243 | * 244 | * Outputs: zeroed out pcm buffer 245 | * 246 | * Return: none 247 | **************************************************************************************/ 248 | static void MP3ClearBadFrame(MP3DecInfo *mp3DecInfo, short *outbuf) 249 | { 250 | int i; 251 | 252 | if (!mp3DecInfo) 253 | return; 254 | 255 | for (i = 0; i < mp3DecInfo->nGrans * mp3DecInfo->nGranSamps * mp3DecInfo->nChans; i++) 256 | outbuf[i] = 0; 257 | } 258 | 259 | /************************************************************************************** 260 | * Function: MP3Decode 261 | * 262 | * Description: decode one frame of MP3 data 263 | * 264 | * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) 265 | * double pointer to buffer of MP3 data (containing headers + mainData) 266 | * number of valid bytes remaining in inbuf 267 | * pointer to outbuf, big enough to hold one frame of decoded PCM samples 268 | * flag indicating whether MP3 data is normal MPEG format (useSize = 0) 269 | * or reformatted as "self-contained" frames (useSize = 1) 270 | * 271 | * Outputs: PCM data in outbuf, interleaved LRLRLR... if stereo 272 | * number of output samples = nGrans * nGranSamps * nChans 273 | * updated inbuf pointer, updated bytesLeft 274 | * 275 | * Return: error code, defined in mp3dec.h (0 means no error, < 0 means error) 276 | * 277 | * Notes: switching useSize on and off between frames in the same stream 278 | * is not supported (bit reservoir is not maintained if useSize on) 279 | **************************************************************************************/ 280 | int MP3Decode(HMP3Decoder hMP3Decoder, unsigned char **inbuf, int *bytesLeft, short *outbuf, int useSize) 281 | { 282 | int offset, bitOffset, mainBits, gr, ch, fhBytes, siBytes, freeFrameBytes; 283 | int prevBitOffset, sfBlockBits, huffBlockBits; 284 | unsigned char *mainPtr; 285 | MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; 286 | // ULONG32 ulTime; 287 | // StartYield(&ulTime); 288 | if (!mp3DecInfo) 289 | return ERR_MP3_NULL_POINTER; 290 | 291 | /* unpack frame header */ 292 | fhBytes = UnpackFrameHeader(mp3DecInfo, *inbuf); 293 | if (fhBytes < 0) 294 | return ERR_MP3_INVALID_FRAMEHEADER; /* don't clear outbuf since we don't know size (failed to parse header) */ 295 | *inbuf += fhBytes; 296 | 297 | /* unpack side info */ 298 | siBytes = UnpackSideInfo(mp3DecInfo, *inbuf); 299 | if (siBytes < 0) { 300 | MP3ClearBadFrame(mp3DecInfo, outbuf); 301 | return ERR_MP3_INVALID_SIDEINFO; 302 | } 303 | *inbuf += siBytes; 304 | *bytesLeft -= (fhBytes + siBytes); 305 | 306 | /* if free mode, need to calculate bitrate and nSlots manually, based on frame size */ 307 | if (mp3DecInfo->bitrate == 0 || mp3DecInfo->freeBitrateFlag) { 308 | if (!mp3DecInfo->freeBitrateFlag) { 309 | /* first time through, need to scan for next sync word and figure out frame size */ 310 | mp3DecInfo->freeBitrateFlag = 1; 311 | mp3DecInfo->freeBitrateSlots = MP3FindFreeSync(*inbuf, *inbuf - fhBytes - siBytes, *bytesLeft); 312 | if (mp3DecInfo->freeBitrateSlots < 0) { 313 | MP3ClearBadFrame(mp3DecInfo, outbuf); 314 | return ERR_MP3_FREE_BITRATE_SYNC; 315 | } 316 | freeFrameBytes = mp3DecInfo->freeBitrateSlots + fhBytes + siBytes; 317 | mp3DecInfo->bitrate = (freeFrameBytes * mp3DecInfo->samprate * 8) / (mp3DecInfo->nGrans * mp3DecInfo->nGranSamps); 318 | } 319 | mp3DecInfo->nSlots = mp3DecInfo->freeBitrateSlots + CheckPadBit(mp3DecInfo); /* add pad byte, if required */ 320 | } 321 | 322 | /* useSize != 0 means we're getting reformatted (RTP) packets (see RFC 3119) 323 | * - calling function assembles "self-contained" MP3 frames by shifting any main_data 324 | * from the bit reservoir (in previous frames) to AFTER the sync word and side info 325 | * - calling function should set mainDataBegin to 0, and tell us exactly how large this 326 | * frame is (in bytesLeft) 327 | */ 328 | if (useSize) { 329 | mp3DecInfo->nSlots = *bytesLeft; 330 | if (mp3DecInfo->mainDataBegin != 0 || mp3DecInfo->nSlots <= 0) { 331 | /* error - non self-contained frame, or missing frame (size <= 0), could do loss concealment here */ 332 | MP3ClearBadFrame(mp3DecInfo, outbuf); 333 | return ERR_MP3_INVALID_FRAMEHEADER; 334 | } 335 | 336 | /* can operate in-place on reformatted frames */ 337 | mp3DecInfo->mainDataBytes = mp3DecInfo->nSlots; 338 | mainPtr = *inbuf; 339 | *inbuf += mp3DecInfo->nSlots; 340 | *bytesLeft -= (mp3DecInfo->nSlots); 341 | } else { 342 | /* out of data - assume last or truncated frame */ 343 | if (mp3DecInfo->nSlots > *bytesLeft) { 344 | MP3ClearBadFrame(mp3DecInfo, outbuf); 345 | return ERR_MP3_INDATA_UNDERFLOW; 346 | } 347 | /* fill main data buffer with enough new data for this frame */ 348 | if (mp3DecInfo->mainDataBytes >= mp3DecInfo->mainDataBegin) { 349 | /* adequate "old" main data available (i.e. bit reservoir) */ 350 | memmove(mp3DecInfo->mainBuf, mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes - mp3DecInfo->mainDataBegin, mp3DecInfo->mainDataBegin); 351 | memcpy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBegin, *inbuf, mp3DecInfo->nSlots); 352 | 353 | mp3DecInfo->mainDataBytes = mp3DecInfo->mainDataBegin + mp3DecInfo->nSlots; 354 | *inbuf += mp3DecInfo->nSlots; 355 | *bytesLeft -= (mp3DecInfo->nSlots); 356 | mainPtr = mp3DecInfo->mainBuf; 357 | } else { 358 | /* not enough data in bit reservoir from previous frames (perhaps starting in middle of file) */ 359 | memcpy(mp3DecInfo->mainBuf + mp3DecInfo->mainDataBytes, *inbuf, mp3DecInfo->nSlots); 360 | mp3DecInfo->mainDataBytes += mp3DecInfo->nSlots; 361 | *inbuf += mp3DecInfo->nSlots; 362 | *bytesLeft -= (mp3DecInfo->nSlots); 363 | MP3ClearBadFrame(mp3DecInfo, outbuf); 364 | return ERR_MP3_MAINDATA_UNDERFLOW; 365 | } 366 | } 367 | bitOffset = 0; 368 | mainBits = mp3DecInfo->mainDataBytes * 8; 369 | 370 | /* decode one complete frame */ 371 | for (gr = 0; gr < mp3DecInfo->nGrans; gr++) { 372 | for (ch = 0; ch < mp3DecInfo->nChans; ch++) { 373 | /* unpack scale factors and compute size of scale factor block */ 374 | prevBitOffset = bitOffset; 375 | offset = UnpackScaleFactors(mp3DecInfo, mainPtr, &bitOffset, mainBits, gr, ch); 376 | 377 | sfBlockBits = 8*offset - prevBitOffset + bitOffset; 378 | huffBlockBits = mp3DecInfo->part23Length[gr][ch] - sfBlockBits; 379 | mainPtr += offset; 380 | mainBits -= sfBlockBits; 381 | 382 | if (offset < 0 || mainBits < huffBlockBits) { 383 | MP3ClearBadFrame(mp3DecInfo, outbuf); 384 | return ERR_MP3_INVALID_SCALEFACT; 385 | } 386 | 387 | /* decode Huffman code words */ 388 | prevBitOffset = bitOffset; 389 | offset = DecodeHuffman(mp3DecInfo, mainPtr, &bitOffset, huffBlockBits, gr, ch); 390 | if (offset < 0) { 391 | MP3ClearBadFrame(mp3DecInfo, outbuf); 392 | return ERR_MP3_INVALID_HUFFCODES; 393 | } 394 | 395 | mainPtr += offset; 396 | mainBits -= (8*offset - prevBitOffset + bitOffset); 397 | } 398 | // YieldIfRequired(&ulTime); 399 | /* dequantize coefficients, decode stereo, reorder short blocks */ 400 | if (Dequantize(mp3DecInfo, gr) < 0) { 401 | MP3ClearBadFrame(mp3DecInfo, outbuf); 402 | return ERR_MP3_INVALID_DEQUANTIZE; 403 | } 404 | 405 | /* alias reduction, inverse MDCT, overlap-add, frequency inversion */ 406 | for (ch = 0; ch < mp3DecInfo->nChans; ch++) 407 | if (IMDCT(mp3DecInfo, gr, ch) < 0) { 408 | MP3ClearBadFrame(mp3DecInfo, outbuf); 409 | return ERR_MP3_INVALID_IMDCT; 410 | } 411 | 412 | /* subband transform - if stereo, interleaves pcm LRLRLR */ 413 | if (Subband(mp3DecInfo, outbuf + gr*mp3DecInfo->nGranSamps*mp3DecInfo->nChans) < 0) { 414 | MP3ClearBadFrame(mp3DecInfo, outbuf); 415 | return ERR_MP3_INVALID_SUBBAND; 416 | } 417 | } 418 | return ERR_MP3_NONE; 419 | } -------------------------------------------------------------------------------- /src/mp3dec.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * mp3dec.h - public C API for MP3 decoder 42 | **************************************************************************************/ 43 | 44 | #ifndef _MP3DEC_H 45 | #define _MP3DEC_H 46 | 47 | #ifdef ARDUINO 48 | #include 49 | #endif 50 | 51 | #if defined(_WIN32) && !defined(_WIN32_WCE) 52 | # 53 | #elif defined(_WIN32) && defined(_WIN32_WCE) && defined(ARM) 54 | # 55 | #elif defined(_WIN32) && defined(WINCE_EMULATOR) 56 | # 57 | #elif defined(ARM_ADS) 58 | # 59 | #elif defined(_SYMBIAN) && defined(__WINS__) /* Symbian emulator for Ix86 */ 60 | # 61 | #elif defined(__GNUC__) && defined(ARM) 62 | # 63 | #elif defined(__GNUC__) && defined(__ARMEL__) 64 | # 65 | #elif defined(__GNUC__) && defined(__i386__) 66 | # 67 | #elif defined(__GNUC__) && defined(__amd64__) 68 | # 69 | #elif defined(_OPENWAVE_SIMULATOR) || defined(_OPENWAVE_ARMULATOR) 70 | # 71 | #elif defined(__GNUC__) && defined(__AVR32_UC__) 72 | # 73 | #elif defined(__CORTEX_M) && __CORTEX_M == 0x04U 74 | # 75 | #elif defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__) /* teensy 3.6, 3.5, or 3.1/2 */ 76 | # 77 | #elif defined(MP3DEC_GENERIC) 78 | # 79 | #else 80 | #error No platform defined. See valid options in mp3dec.h 81 | #endif 82 | 83 | #ifdef __cplusplus 84 | extern "C" { 85 | #endif 86 | 87 | /* determining MAINBUF_SIZE: 88 | * max mainDataBegin = (2^9 - 1) bytes (since 9-bit offset) = 511 89 | * max nSlots (concatenated with mainDataBegin bytes from before) = 1440 - 9 - 4 + 1 = 1428 90 | * 511 + 1428 = 1939, round up to 1940 (4-byte align) 91 | */ 92 | #define MAINBUF_SIZE 1940 93 | 94 | #define MAX_NGRAN 2 /* max granules */ 95 | #define MAX_NCHAN 2 /* max channels */ 96 | #define MAX_NSAMP 576 /* max samples per channel, per granule */ 97 | 98 | /* map to 0,1,2 to make table indexing easier */ 99 | typedef enum { 100 | MPEG1 = 0, 101 | MPEG2 = 1, 102 | MPEG25 = 2 103 | } MPEGVersion; 104 | 105 | typedef void *HMP3Decoder; 106 | 107 | enum { 108 | ERR_MP3_NONE = 0, 109 | ERR_MP3_INDATA_UNDERFLOW = -1, 110 | ERR_MP3_MAINDATA_UNDERFLOW = -2, 111 | ERR_MP3_FREE_BITRATE_SYNC = -3, 112 | ERR_MP3_OUT_OF_MEMORY = -4, 113 | ERR_MP3_NULL_POINTER = -5, 114 | ERR_MP3_INVALID_FRAMEHEADER = -6, 115 | ERR_MP3_INVALID_SIDEINFO = -7, 116 | ERR_MP3_INVALID_SCALEFACT = -8, 117 | ERR_MP3_INVALID_HUFFCODES = -9, 118 | ERR_MP3_INVALID_DEQUANTIZE = -10, 119 | ERR_MP3_INVALID_IMDCT = -11, 120 | ERR_MP3_INVALID_SUBBAND = -12, 121 | 122 | ERR_UNKNOWN = -9999 123 | }; 124 | 125 | typedef struct _MP3FrameInfo { 126 | int bitrate; 127 | int nChans; 128 | int samprate; 129 | int bitsPerSample; 130 | int outputSamps; 131 | int layer; 132 | int version; 133 | } MP3FrameInfo; 134 | 135 | /* public API */ 136 | HMP3Decoder MP3InitDecoder(void); 137 | void MP3FreeDecoder(HMP3Decoder hMP3Decoder); 138 | int MP3Decode(HMP3Decoder hMP3Decoder, unsigned char **inbuf, int *bytesLeft, short *outbuf, int useSize); 139 | 140 | void MP3GetLastFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo); 141 | int MP3GetNextFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo, unsigned char *buf); 142 | int MP3FindSyncWord(unsigned char *buf, int nBytes); 143 | 144 | #ifdef __cplusplus 145 | } 146 | #endif 147 | 148 | #endif /* _MP3DEC_H */ 149 | -------------------------------------------------------------------------------- /src/mp3tabs.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * mp3tabs.c - platform-independent tables for MP3 decoder (global, read-only) 42 | **************************************************************************************/ 43 | 44 | #include "mp3common.h" 45 | 46 | /* indexing = [version][samplerate index] 47 | * sample rate of frame (Hz) 48 | */ 49 | const int samplerateTab[3][3] = { 50 | {44100, 48000, 32000}, /* MPEG-1 */ 51 | {22050, 24000, 16000}, /* MPEG-2 */ 52 | {11025, 12000, 8000}, /* MPEG-2.5 */ 53 | }; 54 | 55 | /* indexing = [version][layer][bitrate index] 56 | * bitrate (kbps) of frame 57 | * - bitrate index == 0 is "free" mode (bitrate determined on the fly by 58 | * counting bits between successive sync words) 59 | */ 60 | const short bitrateTab[3][3][15] = { 61 | { 62 | /* MPEG-1 */ 63 | { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448}, /* Layer 1 */ 64 | { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384}, /* Layer 2 */ 65 | { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}, /* Layer 3 */ 66 | }, 67 | { 68 | /* MPEG-2 */ 69 | { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256}, /* Layer 1 */ 70 | { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 2 */ 71 | { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 3 */ 72 | }, 73 | { 74 | /* MPEG-2.5 */ 75 | { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256}, /* Layer 1 */ 76 | { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 2 */ 77 | { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 3 */ 78 | }, 79 | }; 80 | 81 | /* indexing = [version][layer] 82 | * number of samples in one frame (per channel) 83 | */ 84 | const short samplesPerFrameTab[3][3] = { 85 | {384, 1152, 1152 }, /* MPEG1 */ 86 | {384, 1152, 576 }, /* MPEG2 */ 87 | {384, 1152, 576 }, /* MPEG2.5 */ 88 | }; 89 | 90 | /* layers 1, 2, 3 */ 91 | const short bitsPerSlotTab[3] = {32, 8, 8}; 92 | 93 | /* indexing = [version][mono/stereo] 94 | * number of bytes in side info section of bitstream 95 | */ 96 | const short sideBytesTab[3][2] = { 97 | {17, 32}, /* MPEG-1: mono, stereo */ 98 | { 9, 17}, /* MPEG-2: mono, stereo */ 99 | { 9, 17}, /* MPEG-2.5: mono, stereo */ 100 | }; 101 | 102 | /* indexing = [version][sampleRate][bitRate] 103 | * for layer3, nSlots = floor(samps/frame * bitRate / sampleRate / 8) 104 | * - add one pad slot if necessary 105 | */ 106 | const short slotTab[3][3][15] = { 107 | { 108 | /* MPEG-1 */ 109 | { 0, 104, 130, 156, 182, 208, 261, 313, 365, 417, 522, 626, 731, 835,1044 }, /* 44 kHz */ 110 | { 0, 96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, 672, 768, 960 }, /* 48 kHz */ 111 | { 0, 144, 180, 216, 252, 288, 360, 432, 504, 576, 720, 864,1008,1152,1440 }, /* 32 kHz */ 112 | }, 113 | { 114 | /* MPEG-2 */ 115 | { 0, 26, 52, 78, 104, 130, 156, 182, 208, 261, 313, 365, 417, 470, 522 }, /* 22 kHz */ 116 | { 0, 24, 48, 72, 96, 120, 144, 168, 192, 240, 288, 336, 384, 432, 480 }, /* 24 kHz */ 117 | { 0, 36, 72, 108, 144, 180, 216, 252, 288, 360, 432, 504, 576, 648, 720 }, /* 16 kHz */ 118 | }, 119 | { 120 | /* MPEG-2.5 */ 121 | { 0, 52, 104, 156, 208, 261, 313, 365, 417, 522, 626, 731, 835, 940,1044 }, /* 11 kHz */ 122 | { 0, 48, 96, 144, 192, 240, 288, 336, 384, 480, 576, 672, 768, 864, 960 }, /* 12 kHz */ 123 | { 0, 72, 144, 216, 288, 360, 432, 504, 576, 720, 864,1008,1152,1296,1440 }, /* 8 kHz */ 124 | }, 125 | }; 126 | 127 | /* indexing = [version][sampleRate][long (.l) or short (.s) block] 128 | * sfBandTable[v][s].l[cb] = index of first bin in critical band cb (long blocks) 129 | * sfBandTable[v][s].s[cb] = index of first bin in critical band cb (short blocks) 130 | */ 131 | const SFBandTable sfBandTable[3][3] = { 132 | { 133 | /* MPEG-1 (44, 48, 32 kHz) */ 134 | { 135 | { 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90,110,134,162,196,238,288,342,418,576 }, 136 | { 0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84,106,136,192 } 137 | }, 138 | { 139 | { 0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88,106,128,156,190,230,276,330,384,576 }, 140 | { 0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80,100,126,192 } 141 | }, 142 | { 143 | { 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82,102,126,156,194,240,296,364,448,550,576 }, 144 | { 0, 4, 8, 12, 16, 22, 30, 42, 58, 78,104,138,180,192 } 145 | } 146 | }, 147 | 148 | { 149 | /* MPEG-2 (22, 24, 16 kHz) */ 150 | { 151 | { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 }, 152 | { 0, 4, 8, 12, 18, 24, 32, 42, 56, 74,100,132,174,192 } 153 | }, 154 | { 155 | { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,114,136,162,194,232,278,332,394,464,540,576 }, 156 | { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,136,180,192 } 157 | }, 158 | { 159 | { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 }, 160 | { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 } 161 | }, 162 | }, 163 | 164 | { 165 | /* MPEG-2.5 (11, 12, 8 kHz) */ 166 | { 167 | { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 }, 168 | { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 } 169 | }, 170 | { 171 | { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 }, 172 | { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 } 173 | }, 174 | { 175 | { 0, 12, 24, 36, 48, 60, 72, 88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576 }, 176 | { 0, 8, 16, 24, 36, 52, 72, 96,124,160,162,164,166,192 } 177 | }, 178 | }, 179 | }; 180 | 181 | 182 | -------------------------------------------------------------------------------- /src/mpadecobjfixpt.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | #ifndef _MPADECOBJFIXPT_H_ 37 | #define _MPADECOBJFIXPT_H_ 38 | 39 | #include "mp3dec.h" /* public C API for new MP3 decoder */ 40 | 41 | class CMpaDecObj 42 | { 43 | public: 44 | CMpaDecObj(); 45 | ~CMpaDecObj(); 46 | 47 | /////////////////////////////////////////////////////////////////////////// 48 | // Function: Init_n 49 | // Purpose: Initialize the mp3 decoder. 50 | // Parameters: pSync a pointer to a syncword 51 | // ulSize the size of the buffer pSync points to 52 | // bUseSize this tells the decoder to use the input frame 53 | // size on the decode instead of calculating 54 | // the frame size. This is necessary when 55 | // our formatted mp3 data (main_data_begin always 56 | // equal to 0). 57 | // 58 | // Returns: returns 1 on success, 0 on failure 59 | /////////////////////////////////////////////////////////////////////////// 60 | int Init_n(unsigned char *pSync, 61 | unsigned long ulSize, 62 | unsigned char bUseSize=0); 63 | 64 | /////////////////////////////////////////////////////////////////////////// 65 | // Function: DecodeFrame_v 66 | // Purpose: Decodes one mp3 frame 67 | // Parameters: pSource pointer to an mp3 frame (at a syncword) 68 | // pulSize size of the buffer pSource points to. It will 69 | // contain the number of mp3 bytes decoded upon 70 | // return. 71 | // pPCM pointer to a buffer to decode into 72 | // pulPCMSize size of the PCM buffer. It will contain the 73 | // number of PCM bytes prodced upon return. 74 | /////////////////////////////////////////////////////////////////////////// 75 | void DecodeFrame_v(unsigned char *pSource, 76 | unsigned long *pulSize, 77 | unsigned char *pPCM, 78 | unsigned long *pulPCMSize); 79 | 80 | // overloaded new version that returns error code in errCode 81 | void DecodeFrame_v(unsigned char *pSource, 82 | unsigned long *pulSize, 83 | unsigned char *pPCM, 84 | unsigned long *pulPCMSize, 85 | int *errCode); 86 | 87 | void GetPCMInfo_v(unsigned long &ulSampRate, 88 | int &nChannels, 89 | int &nBitsPerSample); 90 | 91 | // return number of samples per frame, PER CHANNEL (renderer multiplies this result by nChannels) 92 | int GetSamplesPerFrame_n(); 93 | 94 | void SetTrustPackets(unsigned char bTrust) { m_bTrustPackets = bTrust; } 95 | 96 | private: 97 | void * m_pDec; // generic void ptr 98 | 99 | void * m_pDecL1; // not implemented (could use old Xing mpadecl1.cpp) 100 | void * m_pDecL2; // not implemented (could use old Xing mpadecl2.cpp) 101 | HMP3Decoder m_pDecL3; 102 | 103 | MP3FrameInfo m_lastMP3FrameInfo; 104 | unsigned char m_bUseFrameSize; 105 | unsigned char m_bTrustPackets; 106 | }; 107 | 108 | #endif /* _MPADECOBJFIXPT_H_ */ 109 | -------------------------------------------------------------------------------- /src/polyphase.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * polyphase.c - final stage of subband transform (polyphase synthesis filter) 42 | * 43 | * This is the C reference version using __int64 44 | * Look in the appropriate subdirectories for optimized asm implementations 45 | * (e.g. arm/asmpoly.s) 46 | **************************************************************************************/ 47 | 48 | #include "coder.h" 49 | #include "assembly.h" 50 | 51 | /* input to Polyphase = Q(DQ_FRACBITS_OUT-2), gain 2 bits in convolution 52 | * we also have the implicit bias of 2^15 to add back, so net fraction bits = 53 | * DQ_FRACBITS_OUT - 2 - 2 - 15 54 | * (see comment on Dequantize() for more info) 55 | */ 56 | #define DEF_NFRACBITS (DQ_FRACBITS_OUT - 2 - 2 - 15) 57 | #define CSHIFT 12 /* coefficients have 12 leading sign bits for early-terminating mulitplies */ 58 | 59 | static __inline short ClipToShort(int x, int fracBits) 60 | { 61 | int sign; 62 | 63 | /* assumes you've already rounded (x += (1 << (fracBits-1))) */ 64 | x >>= fracBits; 65 | 66 | /* Ken's trick: clips to [-32768, 32767] */ 67 | sign = x >> 31; 68 | if (sign != (x >> 15)) 69 | x = sign ^ ((1 << 15) - 1); 70 | 71 | return (short)x; 72 | } 73 | 74 | #define MC0M(x) { \ 75 | c1 = *coef; coef++; c2 = *coef; coef++; \ 76 | vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \ 77 | sum1L = MADD64(sum1L, vLo, c1); sum1L = MADD64(sum1L, vHi, -c2); \ 78 | } 79 | 80 | #define MC1M(x) { \ 81 | c1 = *coef; coef++; \ 82 | vLo = *(vb1+(x)); \ 83 | sum1L = MADD64(sum1L, vLo, c1); \ 84 | } 85 | 86 | #define MC2M(x) { \ 87 | c1 = *coef; coef++; c2 = *coef; coef++; \ 88 | vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \ 89 | sum1L = MADD64(sum1L, vLo, c1); sum2L = MADD64(sum2L, vLo, c2); \ 90 | sum1L = MADD64(sum1L, vHi, -c2); sum2L = MADD64(sum2L, vHi, c1); \ 91 | } 92 | 93 | /************************************************************************************** 94 | * Function: PolyphaseMono 95 | * 96 | * Description: filter one subband and produce 32 output PCM samples for one channel 97 | * 98 | * Inputs: pointer to PCM output buffer 99 | * number of "extra shifts" (vbuf format = Q(DQ_FRACBITS_OUT-2)) 100 | * pointer to start of vbuf (preserved from last call) 101 | * start of filter coefficient table (in proper, shuffled order) 102 | * no minimum number of guard bits is required for input vbuf 103 | * (see additional scaling comments below) 104 | * 105 | * Outputs: 32 samples of one channel of decoded PCM data, (i.e. Q16.0) 106 | * 107 | * Return: none 108 | * 109 | * TODO: add 32-bit version for platforms where 64-bit mul-acc is not supported 110 | * (note max filter gain - see polyCoef[] comments) 111 | **************************************************************************************/ 112 | void PolyphaseMono(short *pcm, int *vbuf, const int *coefBase) 113 | { 114 | int i; 115 | const int *coef; 116 | int *vb1; 117 | int vLo, vHi, c1, c2; 118 | Word64 sum1L, sum2L, rndVal; 119 | 120 | rndVal = (Word64)( 1 << (DEF_NFRACBITS - 1 + (32 - CSHIFT)) ); 121 | 122 | /* special case, output sample 0 */ 123 | coef = coefBase; 124 | vb1 = vbuf; 125 | sum1L = rndVal; 126 | 127 | c1 = *coef; 128 | coef++; 129 | c2 = *coef; 130 | coef++; 131 | vLo = *(vb1+(0)); 132 | vHi = *(vb1+(23-(0))); 133 | sum1L = MADD64(sum1L, vLo, c1); 134 | sum1L = MADD64(sum1L, vHi, -c2); 135 | 136 | //MC0M(0) // a 137 | MC0M(1) 138 | MC0M(2) 139 | MC0M(3) 140 | MC0M(4) 141 | MC0M(5) 142 | MC0M(6) 143 | MC0M(7) 144 | 145 | *(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS); 146 | 147 | /* special case, output sample 16 */ 148 | coef = coefBase + 256; 149 | vb1 = vbuf + 64*16; 150 | sum1L = rndVal; 151 | 152 | MC1M(0) 153 | MC1M(1) 154 | MC1M(2) 155 | MC1M(3) 156 | MC1M(4) 157 | MC1M(5) 158 | MC1M(6) 159 | MC1M(7) 160 | 161 | *(pcm + 16) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS); 162 | 163 | /* main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17 */ 164 | coef = coefBase + 16; 165 | vb1 = vbuf + 64; 166 | pcm++; 167 | 168 | /* right now, the compiler creates bad asm from this... */ 169 | for (i = 15; i > 0; i--) { 170 | sum1L = sum2L = rndVal; 171 | 172 | MC2M(0) 173 | MC2M(1) 174 | MC2M(2) 175 | MC2M(3) 176 | MC2M(4) 177 | MC2M(5) 178 | MC2M(6) 179 | MC2M(7) 180 | 181 | vb1 += 64; 182 | *(pcm) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS); 183 | *(pcm + 2*i) = ClipToShort((int)SAR64(sum2L, (32-CSHIFT)), DEF_NFRACBITS); 184 | pcm++; 185 | } 186 | } 187 | 188 | #define MC0S(x) { \ 189 | c1 = *coef; coef++; c2 = *coef; coef++; \ 190 | vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \ 191 | sum1L = MADD64(sum1L, vLo, c1); sum1L = MADD64(sum1L, vHi, -c2); \ 192 | vLo = *(vb1+32+(x)); vHi = *(vb1+32+(23-(x))); \ 193 | sum1R = MADD64(sum1R, vLo, c1); sum1R = MADD64(sum1R, vHi, -c2); \ 194 | } 195 | 196 | #define MC1S(x) { \ 197 | c1 = *coef; coef++; \ 198 | vLo = *(vb1+(x)); \ 199 | sum1L = MADD64(sum1L, vLo, c1); \ 200 | vLo = *(vb1+32+(x)); \ 201 | sum1R = MADD64(sum1R, vLo, c1); \ 202 | } 203 | 204 | #define MC2S(x) { \ 205 | c1 = *coef; coef++; c2 = *coef; coef++; \ 206 | vLo = *(vb1+(x)); vHi = *(vb1+(23-(x))); \ 207 | sum1L = MADD64(sum1L, vLo, c1); sum2L = MADD64(sum2L, vLo, c2); \ 208 | sum1L = MADD64(sum1L, vHi, -c2); sum2L = MADD64(sum2L, vHi, c1); \ 209 | vLo = *(vb1+32+(x)); vHi = *(vb1+32+(23-(x))); \ 210 | sum1R = MADD64(sum1R, vLo, c1); sum2R = MADD64(sum2R, vLo, c2); \ 211 | sum1R = MADD64(sum1R, vHi, -c2); sum2R = MADD64(sum2R, vHi, c1); \ 212 | } 213 | 214 | /************************************************************************************** 215 | * Function: PolyphaseStereo 216 | * 217 | * Description: filter one subband and produce 32 output PCM samples for each channel 218 | * 219 | * Inputs: pointer to PCM output buffer 220 | * number of "extra shifts" (vbuf format = Q(DQ_FRACBITS_OUT-2)) 221 | * pointer to start of vbuf (preserved from last call) 222 | * start of filter coefficient table (in proper, shuffled order) 223 | * no minimum number of guard bits is required for input vbuf 224 | * (see additional scaling comments below) 225 | * 226 | * Outputs: 32 samples of two channels of decoded PCM data, (i.e. Q16.0) 227 | * 228 | * Return: none 229 | * 230 | * Notes: interleaves PCM samples LRLRLR... 231 | * 232 | * TODO: add 32-bit version for platforms where 64-bit mul-acc is not supported 233 | **************************************************************************************/ 234 | void PolyphaseStereo(short *pcm, int *vbuf, const int *coefBase) 235 | { 236 | int i; 237 | const int *coef; 238 | int *vb1; 239 | int vLo, vHi, c1, c2; 240 | Word64 sum1L, sum2L, sum1R, sum2R, rndVal; 241 | 242 | rndVal = (Word64)( 1 << (DEF_NFRACBITS - 1 + (32 - CSHIFT)) ); 243 | 244 | /* special case, output sample 0 */ 245 | coef = coefBase; 246 | vb1 = vbuf; 247 | sum1L = sum1R = rndVal; 248 | 249 | MC0S(0) 250 | MC0S(1) 251 | MC0S(2) 252 | MC0S(3) 253 | MC0S(4) 254 | MC0S(5) 255 | MC0S(6) 256 | MC0S(7) 257 | 258 | *(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS); 259 | *(pcm + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS); 260 | 261 | /* special case, output sample 16 */ 262 | coef = coefBase + 256; 263 | vb1 = vbuf + 64*16; 264 | sum1L = sum1R = rndVal; 265 | 266 | MC1S(0) 267 | MC1S(1) 268 | MC1S(2) 269 | MC1S(3) 270 | MC1S(4) 271 | MC1S(5) 272 | MC1S(6) 273 | MC1S(7) 274 | 275 | *(pcm + 2*16 + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS); 276 | *(pcm + 2*16 + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS); 277 | 278 | /* main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17 */ 279 | coef = coefBase + 16; 280 | vb1 = vbuf + 64; 281 | pcm += 2; 282 | 283 | /* right now, the compiler creates bad asm from this... */ 284 | for (i = 15; i > 0; i--) { 285 | sum1L = sum2L = rndVal; 286 | sum1R = sum2R = rndVal; 287 | 288 | MC2S(0) 289 | MC2S(1) 290 | MC2S(2) 291 | MC2S(3) 292 | MC2S(4) 293 | MC2S(5) 294 | MC2S(6) 295 | MC2S(7) 296 | 297 | vb1 += 64; 298 | *(pcm + 0) = ClipToShort((int)SAR64(sum1L, (32-CSHIFT)), DEF_NFRACBITS); 299 | *(pcm + 1) = ClipToShort((int)SAR64(sum1R, (32-CSHIFT)), DEF_NFRACBITS); 300 | *(pcm + 2*2*i + 0) = ClipToShort((int)SAR64(sum2L, (32-CSHIFT)), DEF_NFRACBITS); 301 | *(pcm + 2*2*i + 1) = ClipToShort((int)SAR64(sum2R, (32-CSHIFT)), DEF_NFRACBITS); 302 | pcm += 2; 303 | } 304 | } 305 | -------------------------------------------------------------------------------- /src/readme.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/Adafruit_MP3/630f464fe0d275e82628e6d3cb2b464f28f8485b/src/readme.txt -------------------------------------------------------------------------------- /src/scalfact.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * scalfact.c - scalefactor unpacking functions 42 | **************************************************************************************/ 43 | 44 | #include "coder.h" 45 | 46 | /* scale factor lengths (num bits) */ 47 | static const char SFLenTab[16][2] = { 48 | {0, 0}, {0, 1}, 49 | {0, 2}, {0, 3}, 50 | {3, 0}, {1, 1}, 51 | {1, 2}, {1, 3}, 52 | {2, 1}, {2, 2}, 53 | {2, 3}, {3, 1}, 54 | {3, 2}, {3, 3}, 55 | {4, 2}, {4, 3}, 56 | }; 57 | 58 | /************************************************************************************** 59 | * Function: UnpackSFMPEG1 60 | * 61 | * Description: unpack MPEG 1 scalefactors from bitstream 62 | * 63 | * Inputs: BitStreamInfo, SideInfoSub, ScaleFactorInfoSub structs for this 64 | * granule/channel 65 | * vector of scfsi flags from side info, length = 4 (MAX_SCFBD) 66 | * index of current granule 67 | * ScaleFactorInfoSub from granule 0 (for granule 1, if scfsi[i] is set, 68 | * then we just replicate the scale factors from granule 0 in the 69 | * i'th set of scalefactor bands) 70 | * 71 | * Outputs: updated BitStreamInfo struct 72 | * scalefactors in sfis (short and/or long arrays, as appropriate) 73 | * 74 | * Return: none 75 | * 76 | * Notes: set order of short blocks to s[band][window] instead of s[window][band] 77 | * so that we index through consectutive memory locations when unpacking 78 | * (make sure dequantizer follows same convention) 79 | * Illegal Intensity Position = 7 (always) for MPEG1 scale factors 80 | **************************************************************************************/ 81 | static void UnpackSFMPEG1(BitStreamInfo *bsi, SideInfoSub *sis, ScaleFactorInfoSub *sfis, int *scfsi, int gr, ScaleFactorInfoSub *sfisGr0) 82 | { 83 | int sfb; 84 | int slen0, slen1; 85 | 86 | /* these can be 0, so make sure GetBits(bsi, 0) returns 0 (no >> 32 or anything) */ 87 | slen0 = (int)SFLenTab[sis->sfCompress][0]; 88 | slen1 = (int)SFLenTab[sis->sfCompress][1]; 89 | 90 | if (sis->blockType == 2) { 91 | /* short block, type 2 (implies winSwitchFlag == 1) */ 92 | if (sis->mixedBlock) { 93 | /* do long block portion */ 94 | for (sfb = 0; sfb < 8; sfb++) 95 | sfis->l[sfb] = (char)GetBits(bsi, slen0); 96 | sfb = 3; 97 | } else { 98 | /* all short blocks */ 99 | sfb = 0; 100 | } 101 | 102 | for ( ; sfb < 6; sfb++) { 103 | sfis->s[sfb][0] = (char)GetBits(bsi, slen0); 104 | sfis->s[sfb][1] = (char)GetBits(bsi, slen0); 105 | sfis->s[sfb][2] = (char)GetBits(bsi, slen0); 106 | } 107 | 108 | for ( ; sfb < 12; sfb++) { 109 | sfis->s[sfb][0] = (char)GetBits(bsi, slen1); 110 | sfis->s[sfb][1] = (char)GetBits(bsi, slen1); 111 | sfis->s[sfb][2] = (char)GetBits(bsi, slen1); 112 | } 113 | 114 | /* last sf band not transmitted */ 115 | sfis->s[12][0] = sfis->s[12][1] = sfis->s[12][2] = 0; 116 | } else { 117 | /* long blocks, type 0, 1, or 3 */ 118 | if(gr == 0) { 119 | /* first granule */ 120 | for (sfb = 0; sfb < 11; sfb++) 121 | sfis->l[sfb] = (char)GetBits(bsi, slen0); 122 | for (sfb = 11; sfb < 21; sfb++) 123 | sfis->l[sfb] = (char)GetBits(bsi, slen1); 124 | return; 125 | } else { 126 | /* second granule 127 | * scfsi: 0 = different scalefactors for each granule, 1 = copy sf's from granule 0 into granule 1 128 | * for block type == 2, scfsi is always 0 129 | */ 130 | sfb = 0; 131 | if(scfsi[0]) for( ; sfb < 6 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb]; 132 | else for( ; sfb < 6 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen0); 133 | if(scfsi[1]) for( ; sfb <11 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb]; 134 | else for( ; sfb <11 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen0); 135 | if(scfsi[2]) for( ; sfb <16 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb]; 136 | else for( ; sfb <16 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen1); 137 | if(scfsi[3]) for( ; sfb <21 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb]; 138 | else for( ; sfb <21 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen1); 139 | } 140 | /* last sf band not transmitted */ 141 | sfis->l[21] = 0; 142 | sfis->l[22] = 0; 143 | } 144 | } 145 | 146 | /* NRTab[size + 3*is_right][block type][partition] 147 | * block type index: 0 = (bt0,bt1,bt3), 1 = bt2 non-mixed, 2 = bt2 mixed 148 | * partition: scale factor groups (sfb1 through sfb4) 149 | * for block type = 2 (mixed or non-mixed) / by 3 is rolled into this table 150 | * (for 3 short blocks per long block) 151 | * see 2.4.3.2 in MPEG 2 (low sample rate) spec 152 | * stuff rolled into this table: 153 | * NRTab[x][1][y] --> (NRTab[x][1][y]) / 3 154 | * NRTab[x][2][>=1] --> (NRTab[x][2][>=1]) / 3 (first partition is long block) 155 | */ 156 | static const char NRTab[6][3][4] = { 157 | /* non-intensity stereo */ 158 | { {6, 5, 5, 5}, 159 | {3, 3, 3, 3}, /* includes / 3 */ 160 | {6, 3, 3, 3}, /* includes / 3 except for first entry */ 161 | }, 162 | { {6, 5, 7, 3}, 163 | {3, 3, 4, 2}, 164 | {6, 3, 4, 2}, 165 | }, 166 | { {11, 10, 0, 0}, 167 | {6, 6, 0, 0}, 168 | {6, 3, 6, 0}, /* spec = [15,18,0,0], but 15 = 6L + 9S, so move 9/3=3 into col 1, 18/3=6 into col 2 and adj. slen[1,2] below */ 169 | }, 170 | /* intensity stereo, right chan */ 171 | { {7, 7, 7, 0}, 172 | {4, 4, 4, 0}, 173 | {6, 5, 4, 0}, 174 | }, 175 | { {6, 6, 6, 3}, 176 | {4, 3, 3, 2}, 177 | {6, 4, 3, 2}, 178 | }, 179 | { {8, 8, 5, 0}, 180 | {5, 4, 3, 0}, 181 | {6, 6, 3, 0}, 182 | } 183 | }; 184 | 185 | /************************************************************************************** 186 | * Function: UnpackSFMPEG2 187 | * 188 | * Description: unpack MPEG 2 scalefactors from bitstream 189 | * 190 | * Inputs: BitStreamInfo, SideInfoSub, ScaleFactorInfoSub structs for this 191 | * granule/channel 192 | * index of current granule and channel 193 | * ScaleFactorInfoSub from this granule 194 | * modeExt field from frame header, to tell whether intensity stereo is on 195 | * ScaleFactorJS struct for storing IIP info used in Dequant() 196 | * 197 | * Outputs: updated BitStreamInfo struct 198 | * scalefactors in sfis (short and/or long arrays, as appropriate) 199 | * updated intensityScale and preFlag flags 200 | * 201 | * Return: none 202 | * 203 | * Notes: Illegal Intensity Position = (2^slen) - 1 for MPEG2 scale factors 204 | * 205 | * TODO: optimize the / and % stuff (only do one divide, get modulo x 206 | * with (x / m) * m, etc.) 207 | **************************************************************************************/ 208 | static void UnpackSFMPEG2(BitStreamInfo *bsi, SideInfoSub *sis, ScaleFactorInfoSub *sfis, int gr, int ch, int modeExt, ScaleFactorJS *sfjs) 209 | { 210 | 211 | int i, sfb, sfcIdx, btIdx, nrIdx; 212 | int slen[4], nr[4]; 213 | int sfCompress, preFlag, intensityScale; 214 | 215 | sfCompress = sis->sfCompress; 216 | preFlag = 0; 217 | intensityScale = 0; 218 | 219 | /* stereo mode bits (1 = on): bit 1 = mid-side on/off, bit 0 = intensity on/off */ 220 | if (! ((modeExt & 0x01) && (ch == 1)) ) { 221 | /* in other words: if ((modeExt & 0x01) == 0 || ch == 0) */ 222 | if (sfCompress < 400) { 223 | /* max slen = floor[(399/16) / 5] = 4 */ 224 | slen[0] = (sfCompress >> 4) / 5; 225 | slen[1]= (sfCompress >> 4) % 5; 226 | slen[2]= (sfCompress & 0x0f) >> 2; 227 | slen[3]= (sfCompress & 0x03); 228 | sfcIdx = 0; 229 | } else if (sfCompress < 500) { 230 | /* max slen = floor[(99/4) / 5] = 4 */ 231 | sfCompress -= 400; 232 | slen[0] = (sfCompress >> 2) / 5; 233 | slen[1]= (sfCompress >> 2) % 5; 234 | slen[2]= (sfCompress & 0x03); 235 | slen[3]= 0; 236 | sfcIdx = 1; 237 | } else { 238 | /* max slen = floor[11/3] = 3 (sfCompress = 9 bits in MPEG2) */ 239 | sfCompress -= 500; 240 | slen[0] = sfCompress / 3; 241 | slen[1] = sfCompress % 3; 242 | slen[2] = slen[3] = 0; 243 | if (sis->mixedBlock) { 244 | /* adjust for long/short mix logic (see comment above in NRTab[] definition) */ 245 | slen[2] = slen[1]; 246 | slen[1] = slen[0]; 247 | } 248 | preFlag = 1; 249 | sfcIdx = 2; 250 | } 251 | } else { 252 | /* intensity stereo ch = 1 (right) */ 253 | intensityScale = sfCompress & 0x01; 254 | sfCompress >>= 1; 255 | if (sfCompress < 180) { 256 | /* max slen = floor[35/6] = 5 (from mod 36) */ 257 | slen[0] = (sfCompress / 36); 258 | slen[1] = (sfCompress % 36) / 6; 259 | slen[2] = (sfCompress % 36) % 6; 260 | slen[3] = 0; 261 | sfcIdx = 3; 262 | } else if (sfCompress < 244) { 263 | /* max slen = floor[63/16] = 3 */ 264 | sfCompress -= 180; 265 | slen[0] = (sfCompress & 0x3f) >> 4; 266 | slen[1] = (sfCompress & 0x0f) >> 2; 267 | slen[2] = (sfCompress & 0x03); 268 | slen[3] = 0; 269 | sfcIdx = 4; 270 | } else { 271 | /* max slen = floor[11/3] = 3 (max sfCompress >> 1 = 511/2 = 255) */ 272 | sfCompress -= 244; 273 | slen[0] = (sfCompress / 3); 274 | slen[1] = (sfCompress % 3); 275 | slen[2] = slen[3] = 0; 276 | sfcIdx = 5; 277 | } 278 | } 279 | 280 | /* set index based on block type: (0,1,3) --> 0, (2 non-mixed) --> 1, (2 mixed) ---> 2 */ 281 | btIdx = 0; 282 | if (sis->blockType == 2) 283 | btIdx = (sis->mixedBlock ? 2 : 1); 284 | for (i = 0; i < 4; i++) 285 | nr[i] = (int)NRTab[sfcIdx][btIdx][i]; 286 | 287 | /* save intensity stereo scale factor info */ 288 | if( (modeExt & 0x01) && (ch == 1) ) { 289 | for (i = 0; i < 4; i++) { 290 | sfjs->slen[i] = slen[i]; 291 | sfjs->nr[i] = nr[i]; 292 | } 293 | sfjs->intensityScale = intensityScale; 294 | } 295 | sis->preFlag = preFlag; 296 | 297 | /* short blocks */ 298 | if(sis->blockType == 2) { 299 | if(sis->mixedBlock) { 300 | /* do long block portion */ 301 | for (sfb=0; sfb < 6; sfb++) { 302 | sfis->l[sfb] = (char)GetBits(bsi, slen[0]); 303 | } 304 | sfb = 3; /* start sfb for short */ 305 | nrIdx = 1; 306 | } else { 307 | /* all short blocks, so start nr, sfb at 0 */ 308 | sfb = 0; 309 | nrIdx = 0; 310 | } 311 | 312 | /* remaining short blocks, sfb just keeps incrementing */ 313 | for ( ; nrIdx <= 3; nrIdx++) { 314 | for (i=0; i < nr[nrIdx]; i++, sfb++) { 315 | sfis->s[sfb][0] = (char)GetBits(bsi, slen[nrIdx]); 316 | sfis->s[sfb][1] = (char)GetBits(bsi, slen[nrIdx]); 317 | sfis->s[sfb][2] = (char)GetBits(bsi, slen[nrIdx]); 318 | } 319 | } 320 | /* last sf band not transmitted */ 321 | sfis->s[12][0] = sfis->s[12][1] = sfis->s[12][2] = 0; 322 | } else { 323 | /* long blocks */ 324 | sfb = 0; 325 | for (nrIdx = 0; nrIdx <= 3; nrIdx++) { 326 | for(i=0; i < nr[nrIdx]; i++, sfb++) { 327 | sfis->l[sfb] = (char)GetBits(bsi, slen[nrIdx]); 328 | } 329 | } 330 | /* last sf band not transmitted */ 331 | sfis->l[21] = sfis->l[22] = 0; 332 | 333 | } 334 | } 335 | 336 | /************************************************************************************** 337 | * Function: UnpackScaleFactors 338 | * 339 | * Description: parse the fields of the MP3 scale factor data section 340 | * 341 | * Inputs: MP3DecInfo structure filled by UnpackFrameHeader() and UnpackSideInfo() 342 | * buffer pointing to the MP3 scale factor data 343 | * pointer to bit offset (0-7) indicating starting bit in buf[0] 344 | * number of bits available in data buffer 345 | * index of current granule and channel 346 | * 347 | * Outputs: updated platform-specific ScaleFactorInfo struct 348 | * updated bitOffset 349 | * 350 | * Return: length (in bytes) of scale factor data, -1 if null input pointers 351 | **************************************************************************************/ 352 | int UnpackScaleFactors(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch) 353 | { 354 | int bitsUsed; 355 | unsigned char *startBuf; 356 | BitStreamInfo bitStreamInfo, *bsi; 357 | FrameHeader *fh; 358 | SideInfo *si; 359 | ScaleFactorInfo *sfi; 360 | 361 | /* validate pointers */ 362 | if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS) 363 | return -1; 364 | fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); 365 | si = ((SideInfo *)(mp3DecInfo->SideInfoPS)); 366 | sfi = ((ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS)); 367 | 368 | /* init GetBits reader */ 369 | startBuf = buf; 370 | bsi = &bitStreamInfo; 371 | SetBitstreamPointer(bsi, (bitsAvail + *bitOffset + 7) / 8, buf); 372 | if (*bitOffset) 373 | GetBits(bsi, *bitOffset); 374 | 375 | if (fh->ver == MPEG1) 376 | UnpackSFMPEG1(bsi, &si->sis[gr][ch], &sfi->sfis[gr][ch], si->scfsi[ch], gr, &sfi->sfis[0][ch]); 377 | else 378 | UnpackSFMPEG2(bsi, &si->sis[gr][ch], &sfi->sfis[gr][ch], gr, ch, fh->modeExt, &sfi->sfjs); 379 | 380 | mp3DecInfo->part23Length[gr][ch] = si->sis[gr][ch].part23Length; 381 | 382 | bitsUsed = CalcBitsUsed(bsi, buf, *bitOffset); 383 | buf += (bitsUsed + *bitOffset) >> 3; 384 | *bitOffset = (bitsUsed + *bitOffset) & 0x07; 385 | 386 | return (buf - startBuf); 387 | } 388 | 389 | -------------------------------------------------------------------------------- /src/statname.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * statname.h - name mangling macros for static linking 42 | **************************************************************************************/ 43 | 44 | #ifndef _STATNAME_H 45 | #define _STATNAME_H 46 | 47 | /* define STAT_PREFIX to a unique name for static linking 48 | * all the C functions and global variables will be mangled by the preprocessor 49 | * e.g. void FFT(int *fftbuf) becomes void cook_FFT(int *fftbuf) 50 | */ 51 | #define STAT_PREFIX xmp3 52 | 53 | #define STATCC1(x,y,z) STATCC2(x,y,z) 54 | #define STATCC2(x,y,z) x##y##z 55 | 56 | #ifdef STAT_PREFIX 57 | #define STATNAME(func) STATCC1(STAT_PREFIX, _, func) 58 | #else 59 | #define STATNAME(func) func 60 | #endif 61 | 62 | /* these symbols are common to all implementations */ 63 | #define CheckPadBit STATNAME(CheckPadBit) 64 | #define UnpackFrameHeader STATNAME(UnpackFrameHeader) 65 | #define UnpackSideInfo STATNAME(UnpackSideInfo) 66 | #define AllocateBuffers STATNAME(AllocateBuffers) 67 | #define FreeBuffers STATNAME(FreeBuffers) 68 | #define DecodeHuffman STATNAME(DecodeHuffman) 69 | #define Dequantize STATNAME(Dequantize) 70 | #define IMDCT STATNAME(IMDCT) 71 | #define UnpackScaleFactors STATNAME(UnpackScaleFactors) 72 | #define Subband STATNAME(Subband) 73 | 74 | #define samplerateTab STATNAME(samplerateTab) 75 | #define bitrateTab STATNAME(bitrateTab) 76 | #define samplesPerFrameTab STATNAME(samplesPerFrameTab) 77 | #define bitsPerSlotTab STATNAME(bitsPerSlotTab) 78 | #define sideBytesTab STATNAME(sideBytesTab) 79 | #define slotTab STATNAME(slotTab) 80 | #define sfBandTable STATNAME(sfBandTable) 81 | 82 | /* in your implementation's top-level include file (e.g. real\coder.h) you should 83 | * add new #define sym STATNAME(sym) lines for all the 84 | * additional global functions or variables which your 85 | * implementation uses 86 | */ 87 | 88 | #endif /* _STATNAME_H */ 89 | -------------------------------------------------------------------------------- /src/stproc.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * stproc.c - mid-side and intensity (MPEG1 and MPEG2) stereo processing 42 | **************************************************************************************/ 43 | 44 | #include "coder.h" 45 | #include "assembly.h" 46 | 47 | /************************************************************************************** 48 | * Function: MidSideProc 49 | * 50 | * Description: sum-difference stereo reconstruction 51 | * 52 | * Inputs: vector x with dequantized samples from left and right channels 53 | * number of non-zero samples (MAX of left and right) 54 | * assume 1 guard bit in input 55 | * guard bit mask (left and right channels) 56 | * 57 | * Outputs: updated sample vector x 58 | * updated guard bit mask 59 | * 60 | * Return: none 61 | * 62 | * Notes: assume at least 1 GB in input 63 | **************************************************************************************/ 64 | void MidSideProc(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, int mOut[2]) 65 | { 66 | int i, xr, xl, mOutL, mOutR; 67 | 68 | /* L = (M+S)/sqrt(2), R = (M-S)/sqrt(2) 69 | * NOTE: 1/sqrt(2) done in DequantChannel() - see comments there 70 | */ 71 | mOutL = mOutR = 0; 72 | for(i = 0; i < nSamps; i++) { 73 | xl = x[0][i]; 74 | xr = x[1][i]; 75 | x[0][i] = xl + xr; 76 | x[1][i] = xl - xr; 77 | mOutL |= FASTABS(x[0][i]); 78 | mOutR |= FASTABS(x[1][i]); 79 | } 80 | mOut[0] |= mOutL; 81 | mOut[1] |= mOutR; 82 | } 83 | 84 | /************************************************************************************** 85 | * Function: IntensityProcMPEG1 86 | * 87 | * Description: intensity stereo processing for MPEG1 88 | * 89 | * Inputs: vector x with dequantized samples from left and right channels 90 | * number of non-zero samples in left channel 91 | * valid FrameHeader struct 92 | * two each of ScaleFactorInfoSub, CriticalBandInfo structs (both channels) 93 | * flags indicating midSide on/off, mixedBlock on/off 94 | * guard bit mask (left and right channels) 95 | * 96 | * Outputs: updated sample vector x 97 | * updated guard bit mask 98 | * 99 | * Return: none 100 | * 101 | * Notes: assume at least 1 GB in input 102 | * 103 | * TODO: combine MPEG1/2 into one function (maybe) 104 | * make sure all the mixed-block and IIP logic is right 105 | **************************************************************************************/ 106 | void IntensityProcMPEG1(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, 107 | CriticalBandInfo *cbi, int midSideFlag, int mixFlag, int mOut[2]) 108 | { 109 | int i=0, j=0, n=0, cb=0, w=0; 110 | int sampsLeft, isf, mOutL, mOutR, xl, xr; 111 | int fl, fr, fls[3], frs[3]; 112 | int cbStartL=0, cbStartS=0, cbEndL=0, cbEndS=0; 113 | int *isfTab; 114 | 115 | /* NOTE - this works fine for mixed blocks, as long as the switch point starts in the 116 | * short block section (i.e. on or after sample 36 = sfBand->l[8] = 3*sfBand->s[3] 117 | * is this a safe assumption? 118 | * TODO - intensity + mixed not quite right (diff = 11 on he_mode) 119 | * figure out correct implementation (spec ambiguous about when to do short block reorder) 120 | */ 121 | if (cbi[1].cbType == 0) { 122 | /* long block */ 123 | cbStartL = cbi[1].cbEndL + 1; 124 | cbEndL = cbi[0].cbEndL + 1; 125 | cbStartS = cbEndS = 0; 126 | i = fh->sfBand->l[cbStartL]; 127 | } else if (cbi[1].cbType == 1 || cbi[1].cbType == 2) { 128 | /* short or mixed block */ 129 | cbStartS = cbi[1].cbEndSMax + 1; 130 | cbEndS = cbi[0].cbEndSMax + 1; 131 | cbStartL = cbEndL = 0; 132 | i = 3 * fh->sfBand->s[cbStartS]; 133 | } 134 | 135 | sampsLeft = nSamps - i; /* process to length of left */ 136 | isfTab = (int *)ISFMpeg1[midSideFlag]; 137 | mOutL = mOutR = 0; 138 | 139 | /* long blocks */ 140 | for (cb = cbStartL; cb < cbEndL && sampsLeft > 0; cb++) { 141 | isf = sfis->l[cb]; 142 | if (isf == 7) { 143 | fl = ISFIIP[midSideFlag][0]; 144 | fr = ISFIIP[midSideFlag][1]; 145 | } else { 146 | fl = isfTab[isf]; 147 | fr = isfTab[6] - isfTab[isf]; 148 | } 149 | 150 | n = fh->sfBand->l[cb + 1] - fh->sfBand->l[cb]; 151 | for (j = 0; j < n && sampsLeft > 0; j++, i++) { 152 | xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr); 153 | xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl); 154 | sampsLeft--; 155 | } 156 | } 157 | 158 | /* short blocks */ 159 | for (cb = cbStartS; cb < cbEndS && sampsLeft >= 3; cb++) { 160 | for (w = 0; w < 3; w++) { 161 | isf = sfis->s[cb][w]; 162 | if (isf == 7) { 163 | fls[w] = ISFIIP[midSideFlag][0]; 164 | frs[w] = ISFIIP[midSideFlag][1]; 165 | } else { 166 | fls[w] = isfTab[isf]; 167 | frs[w] = isfTab[6] - isfTab[isf]; 168 | } 169 | } 170 | 171 | n = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb]; 172 | for (j = 0; j < n && sampsLeft >= 3; j++, i+=3) { 173 | xr = MULSHIFT32(frs[0], x[0][i+0]) << 2; x[1][i+0] = xr; mOutR |= FASTABS(xr); 174 | xl = MULSHIFT32(fls[0], x[0][i+0]) << 2; x[0][i+0] = xl; mOutL |= FASTABS(xl); 175 | xr = MULSHIFT32(frs[1], x[0][i+1]) << 2; x[1][i+1] = xr; mOutR |= FASTABS(xr); 176 | xl = MULSHIFT32(fls[1], x[0][i+1]) << 2; x[0][i+1] = xl; mOutL |= FASTABS(xl); 177 | xr = MULSHIFT32(frs[2], x[0][i+2]) << 2; x[1][i+2] = xr; mOutR |= FASTABS(xr); 178 | xl = MULSHIFT32(fls[2], x[0][i+2]) << 2; x[0][i+2] = xl; mOutL |= FASTABS(xl); 179 | sampsLeft -= 3; 180 | } 181 | } 182 | mOut[0] = mOutL; 183 | mOut[1] = mOutR; 184 | 185 | return; 186 | } 187 | 188 | /************************************************************************************** 189 | * Function: IntensityProcMPEG2 190 | * 191 | * Description: intensity stereo processing for MPEG2 192 | * 193 | * Inputs: vector x with dequantized samples from left and right channels 194 | * number of non-zero samples in left channel 195 | * valid FrameHeader struct 196 | * two each of ScaleFactorInfoSub, CriticalBandInfo structs (both channels) 197 | * ScaleFactorJS struct with joint stereo info from UnpackSFMPEG2() 198 | * flags indicating midSide on/off, mixedBlock on/off 199 | * guard bit mask (left and right channels) 200 | * 201 | * Outputs: updated sample vector x 202 | * updated guard bit mask 203 | * 204 | * Return: none 205 | * 206 | * Notes: assume at least 1 GB in input 207 | * 208 | * TODO: combine MPEG1/2 into one function (maybe) 209 | * make sure all the mixed-block and IIP logic is right 210 | * probably redo IIP logic to be simpler 211 | **************************************************************************************/ 212 | void IntensityProcMPEG2(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, 213 | CriticalBandInfo *cbi, ScaleFactorJS *sfjs, int midSideFlag, int mixFlag, int mOut[2]) 214 | { 215 | int i, j, k, n, r, cb, w; 216 | int fl, fr, mOutL, mOutR, xl, xr; 217 | int sampsLeft; 218 | int isf, sfIdx, tmp, il[23]; 219 | int *isfTab; 220 | int cbStartL, cbStartS, cbEndL, cbEndS; 221 | 222 | isfTab = (int *)ISFMpeg2[sfjs->intensityScale][midSideFlag]; 223 | mOutL = mOutR = 0; 224 | 225 | /* fill buffer with illegal intensity positions (depending on slen) */ 226 | for (k = r = 0; r < 4; r++) { 227 | tmp = (1 << sfjs->slen[r]) - 1; 228 | for (j = 0; j < sfjs->nr[r]; j++, k++) 229 | il[k] = tmp; 230 | } 231 | 232 | if (cbi[1].cbType == 0) { 233 | /* long blocks */ 234 | il[21] = il[22] = 1; 235 | cbStartL = cbi[1].cbEndL + 1; /* start at end of right */ 236 | cbEndL = cbi[0].cbEndL + 1; /* process to end of left */ 237 | i = fh->sfBand->l[cbStartL]; 238 | sampsLeft = nSamps - i; 239 | 240 | for(cb = cbStartL; cb < cbEndL; cb++) { 241 | sfIdx = sfis->l[cb]; 242 | if (sfIdx == il[cb]) { 243 | fl = ISFIIP[midSideFlag][0]; 244 | fr = ISFIIP[midSideFlag][1]; 245 | } else { 246 | isf = (sfis->l[cb] + 1) >> 1; 247 | fl = isfTab[(sfIdx & 0x01 ? isf : 0)]; 248 | fr = isfTab[(sfIdx & 0x01 ? 0 : isf)]; 249 | } 250 | n = MIN(fh->sfBand->l[cb + 1] - fh->sfBand->l[cb], sampsLeft); 251 | 252 | for(j = 0; j < n; j++, i++) { 253 | xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr); 254 | xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl); 255 | } 256 | 257 | /* early exit once we've used all the non-zero samples */ 258 | sampsLeft -= n; 259 | if (sampsLeft == 0) 260 | break; 261 | } 262 | } else { 263 | /* short or mixed blocks */ 264 | il[12] = 1; 265 | 266 | for(w = 0; w < 3; w++) { 267 | cbStartS = cbi[1].cbEndS[w] + 1; /* start at end of right */ 268 | cbEndS = cbi[0].cbEndS[w] + 1; /* process to end of left */ 269 | i = 3 * fh->sfBand->s[cbStartS] + w; 270 | 271 | /* skip through sample array by 3, so early-exit logic would be more tricky */ 272 | for(cb = cbStartS; cb < cbEndS; cb++) { 273 | sfIdx = sfis->s[cb][w]; 274 | if (sfIdx == il[cb]) { 275 | fl = ISFIIP[midSideFlag][0]; 276 | fr = ISFIIP[midSideFlag][1]; 277 | } else { 278 | isf = (sfis->s[cb][w] + 1) >> 1; 279 | fl = isfTab[(sfIdx & 0x01 ? isf : 0)]; 280 | fr = isfTab[(sfIdx & 0x01 ? 0 : isf)]; 281 | } 282 | n = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb]; 283 | 284 | for(j = 0; j < n; j++, i+=3) { 285 | xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr); 286 | xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl); 287 | } 288 | } 289 | } 290 | } 291 | mOut[0] = mOutL; 292 | mOut[1] = mOutR; 293 | 294 | return; 295 | } 296 | 297 | -------------------------------------------------------------------------------- /src/subband.c: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: RCSL 1.0/RPSL 1.0 3 | * 4 | * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 5 | * 6 | * The contents of this file, and the files included with this file, are 7 | * subject to the current version of the RealNetworks Public Source License 8 | * Version 1.0 (the "RPSL") available at 9 | * http://www.helixcommunity.org/content/rpsl unless you have licensed 10 | * the file under the RealNetworks Community Source License Version 1.0 11 | * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 12 | * in which case the RCSL will apply. You may also obtain the license terms 13 | * directly from RealNetworks. You may not use this file except in 14 | * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 15 | * applicable to this file, the RCSL. Please see the applicable RPSL or 16 | * RCSL for the rights, obligations and limitations governing use of the 17 | * contents of the file. 18 | * 19 | * This file is part of the Helix DNA Technology. RealNetworks is the 20 | * developer of the Original Code and owns the copyrights in the portions 21 | * it created. 22 | * 23 | * This file, and the files included with this file, is distributed and made 24 | * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 25 | * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 26 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 27 | * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 28 | * 29 | * Technology Compatibility Kit Test Suite(s) Location: 30 | * http://www.helixcommunity.org/content/tck 31 | * 32 | * Contributor(s): 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | /************************************************************************************** 37 | * Fixed-point MP3 decoder 38 | * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) 39 | * June 2003 40 | * 41 | * subband.c - subband transform (synthesis filterbank implemented via 32-point DCT 42 | * followed by polyphase filter) 43 | **************************************************************************************/ 44 | 45 | #include "coder.h" 46 | #include "assembly.h" 47 | 48 | /************************************************************************************** 49 | * Function: Subband 50 | * 51 | * Description: do subband transform on all the blocks in one granule, all channels 52 | * 53 | * Inputs: filled MP3DecInfo structure, after calling IMDCT for all channels 54 | * vbuf[ch] and vindex[ch] must be preserved between calls 55 | * 56 | * Outputs: decoded PCM data, interleaved LRLRLR... if stereo 57 | * 58 | * Return: 0 on success, -1 if null input pointers 59 | **************************************************************************************/ 60 | int Subband(MP3DecInfo *mp3DecInfo, short *pcmBuf) 61 | { 62 | int b; 63 | IMDCTInfo *mi; 64 | SubbandInfo *sbi; 65 | 66 | /* validate pointers */ 67 | if (!mp3DecInfo || !mp3DecInfo->HuffmanInfoPS || !mp3DecInfo->IMDCTInfoPS || !mp3DecInfo->SubbandInfoPS) 68 | return -1; 69 | 70 | mi = (IMDCTInfo *)(mp3DecInfo->IMDCTInfoPS); 71 | sbi = (SubbandInfo*)(mp3DecInfo->SubbandInfoPS); 72 | 73 | if (mp3DecInfo->nChans == 2) { 74 | /* stereo */ 75 | for (b = 0; b < BLOCK_SIZE; b++) { 76 | FDCT32(mi->outBuf[0][b], sbi->vbuf + 0*32, sbi->vindex, (b & 0x01), mi->gb[0]); 77 | FDCT32(mi->outBuf[1][b], sbi->vbuf + 1*32, sbi->vindex, (b & 0x01), mi->gb[1]); 78 | PolyphaseStereo(pcmBuf, sbi->vbuf + sbi->vindex + VBUF_LENGTH * (b & 0x01), polyCoef); 79 | sbi->vindex = (sbi->vindex - (b & 0x01)) & 7; 80 | pcmBuf += (2 * NBANDS); 81 | } 82 | } else { 83 | /* mono */ 84 | for (b = 0; b < BLOCK_SIZE; b++) { 85 | FDCT32(mi->outBuf[0][b], sbi->vbuf + 0*32, sbi->vindex, (b & 0x01), mi->gb[0]); 86 | PolyphaseMono(pcmBuf, sbi->vbuf + sbi->vindex + VBUF_LENGTH * (b & 0x01), polyCoef); 87 | sbi->vindex = (sbi->vindex - (b & 0x01)) & 7; 88 | pcmBuf += NBANDS; 89 | } 90 | } 91 | 92 | return 0; 93 | } 94 | 95 | --------------------------------------------------------------------------------