1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2<html xml:lang="en-US" lang="en-US" xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <meta http-equiv="Content-Style-Type" content="text/css" /> 6 <title>WaveCodecCtr.dll</title> 7 <style type="text/css"> 8 <!-- 9 body { 10 /* 11 font-size : 10pt; 12 */ 13 font-weight : normal; 14 color : #000000; 15 margin : 8px; 16 } 17 18 div { 19 width : 98%; 20 /* white-space : nowrap; */ 21 } 22 23 div.title { 24 text-align : left; 25 font-weight : bold; 26 /* 27 font-size : 16pt; 28 */ 29 font-size : 150%; 30 color : #202020; 31 border-style : double; 32 border-width : 8px; 33 /* タイトルを囲む枠線の色を指定 */ 34 border-color : #CD202C; 35 36 /* RVLプラットフォーム系列 */ 37 /* 38 border-color : #34beed; 39 */ 40 41 /* TWLプラットフォーム系列 */ 42 /* 43 border-color : #ff458f; 44 */ 45 46 margin : 4px; 47 padding : 4px; 48 } 49 H1 { 50 font-size : 150%; 51 font-family : Arial; 52 border-bottom-width : 5px; 53 border-bottom-style : solid; 54 border-bottom-color : #CD202C; 55 padding-bottom : 1px; 56 margin-bottom : 20px; 57 letter-spacing : normal; 58 font-weight : bold; 59 } 60 61 h2 { 62 font-weight : bold; 63 font-size : 150%; 64 border-style : none none solid double; 65 border-width : 0px 0px 2px 8px; 66 border-color : #CD202C; 67 68 margin-left : 2px; 69 padding-left : 4px; 70 } 71 CODE { 72 font-family : "Courier New", monospace; 73 position : normal; 74 left : 12px; 75 font-size : 10pt; 76 } 77 table { 78 margin-top : 2pt; 79 margin-bottom : 2pt; 80 margin-left : 0pt; 81 margin-right : 0pt; 82 padding-left : 0pt; 83 padding-right : 0pt; 84 position : relative; 85 left : 12px; 86 font-family : Arial; 87 font-size : 10pt; 88 border-style : none none none none; 89 } 90 td,th { 91 padding : 2pt; 92 border-width : 2pt; 93 border-style : none none none none; 94 font-style : normal; 95 text-align : left; 96 } 97 td { 98 background : #e8f4f4; 99 font-weight : normal; 100 } 101 th { 102 background : #c0d8d8; 103 font-weight : bold; 104 } 105 106 p { 107 margin-left : 4px; 108 } 109 p.code { 110 font-family : "Courier New", monospace; 111 position : normal; 112 left : 12px; 113 font-size : 10pt; 114 background : #e8f4f4; 115 } 116 117 pre.definition { 118 padding: 10px; 119 background: #F0F0F0; 120 border: 1px solid #CCC; 121 font-size: 13px; 122 } 123 div.subSection { 124 white-space: wrap; 125 } 126 div.subSection pre, 127 div.subSection table, 128 div.subSection p, 129 div.subSection ol 130 { 131 margin-left: 2em; 132 } 133 div.subSection h3 134 { 135 border-bottom: 2px solid #CD202C; 136 padding-bottom: 4px; 137 margin-top: 2em; 138 } 139 div.subSection h4 140 { 141 font-weight: normal; 142 margin-left: .6em; 143 } 144 p.warning { 145 font-weight: bold; 146 color: red; 147 } 148 --> 149 </style> 150 151 152 </head> 153 <body> 154 <h1><CODE>WaveCodecCtr.dll</CODE></h1> 155 <h2>Contents</h2> 156 <ul> 157 <li><a href="#overview">Overview</a></li> 158 <li><a href="#api">Exported Functions</a></li> 159 <li><a href="#sampleCode">Sample Code</a></li> 160 <li><a href="#caution">Cautions for Encoding and Playing Looped Wave Files</a></li> 161 <li><a href="#history">Revision History</a></li> 162 </ul> 163 164 <h2><a name="overview"></a>Overview</h2> 165 <p> 166 <CODE>WaveCodecCtr.dll</CODE> is a Win32 run-time dynamic link library (DLL). This library provides an API for encoding and decoding between 16-bit signed (little-endian) sampling data and the DSP ADPCM compressed format. 167 </p> 168 <p> 169 The DSP ADPCM format is a compressed format that can be played by a CTR system's DSP. It can result in data sizes that are 1/3.5 of 16-bit PCM. This format can be used through the <a href="../api/nn/snd/CTR/Voice/Overview.html"><CODE>nn::snd::Voice</CODE></a> class and the <a href="../api/nn/snd/CTR/WaveBuffer/Overview.html"><CODE>nn::snd::WaveBuffer</CODE></a> structure. 170 </p> 171 <p> 172 This DLL is for developers who want to develop their own tools for creating and previewing DSP ADPCM sampling data. Note that this DLL is single-threaded. 173 </p> 174 <p> 175 <CODE><a href="ctr_WaveConverter.html">ctr_WaveConverter</a></CODE> uses the features of this DLL to create BCWAV files in ADPCM format.</p> 176 177 <h2><a name="api"></a>Exported Functions</h2> 178 <ul> 179 <li><a href="#getBytesForAdpcmBuffer"><CODE>getBytesForAdpcmBuffer</CODE></a></li> 180 <li><a href="#getBytesForAdpcmSamples"><CODE>getBytesForAdpcmSamples</CODE></a></li> 181 <li><a href="#getBytesForPcmBuffer"><CODE>getBytesForPcmBuffer</CODE></a></li> 182 <li><a href="#getBytesForPcmSamples"><CODE>getBytesForPcmSamples</CODE></a></li> 183 <li><a href="#getSampleForAdpcmNibble"><CODE>getSampleForAdpcmNibble</CODE></a></li> 184 <li><a href="#getNibbleAddress"><CODE>getNibbleAddress</CODE></a></li> 185 <li><a href="#getLoopContext"><CODE>getLoopContext</CODE></a></li> 186 <li><a href="#encode"><CODE>encode</CODE></a></li> 187 <li><a href="#decode"><CODE>decode</CODE></a></li> 188 </ul> 189 <div class="subSection"> 190 <h3><a name="getBytesForAdpcmBuffer"></a><CODE>getBytesForAdpcmBuffer</CODE></h3> 191 <h4>Syntax</h4> 192 <pre class="definition">u32 getBytesForAdpcmBuffer(u32 samples);</pre> 193 <h4>Arguments</h4> 194 <table class="arguments"> 195 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 196 <tbody> 197 <tr> 198 <td>in</td> 199 <th>samples</th> 200 <td>Number of (16-bit PCM) samples to encode.</td> 201 </tr> 202 </tbody> 203 </table> 204 <h4>Return Values</h4> 205 <p>The number of bytes required to store the DSP ADPCM-encoded samples.</p> 206 <h4>Description</h4> 207 <p> 208 <CODE>getBytesForAdpcmBuffer</CODE> calculates and returns the number of bytes required to store the sampling data that are being DSP ADPCM-encoded. 209 </p> 210 <p>Note that the number of bytes will be a multiple of the 8-byte length of DSP ADPCM frames.</p> 211 <p>The actual length (in bytes) of the sampling data being encoded will probably be smaller than the value returned by this function. (For more information, see the section <CODE><a href="#getBytesForAdpcmSamples">getBytesForAdpcmSamples</a></CODE>.)</p> 212 <p> 213 Use this function before encoding to allocate storage for the result. 214 </p> 215 216 <h3><a name="getBytesForAdpcmSamples"></a><CODE>getBytesForAdpcmSamples</CODE></h3> 217 <h4>Syntax</h4> 218 <pre class="definition">u32 getBytesForAdpcmSamples(u32 samples);</pre> 219 <h4>Arguments</h4> 220 <table class="arguments"> 221 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 222 <tbody> 223 <tr> 224 <td>in</td> 225 <th>samples</th> 226 <td>Number of (16-bit PCM) samples to encode.</td> 227 </tr> 228 </tbody> 229 </table> 230 <h4>Return Values</h4> 231 <p> The actual length (in bytes) of the encoded sampling data. </p> 232 <h4>Description</h4> 233 <p><CODE>getBytesForAdpcmSamples</CODE> returns the actual number of bytes occupied by the sampling data that are being DSP ADPCM-encoded.</p> 234 235 <h3><a name="getBytesForPcmBuffer"></a><CODE>getBytesForPcmBuffer</CODE></h3> 236 <h4>Syntax</h4> 237 <pre class="definition">u32 getBytesForPcmBuffer(u32 samples); </pre> 238 <h4>Arguments</h4> 239 <table class="arguments"> 240 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 241 <tbody> 242 <tr> 243 <td>in</td> 244 <th>samples</th> 245 <td>The number of samples being decoded.</td> 246 </tr> 247 </tbody> 248 </table> 249 <h4>Return Values</h4> 250 <p>The predicted length (in bytes) of the DSP ADPCM sampling data being decoded.</p> 251 <h4>Description</h4> 252 <p><CODE>getBytesForPcmBuffer</CODE> calculates and returns the number of bytes of data that must be stored after the number of samples passed in the argument have been decoded from the DSP ADPCM format.</p> 253 254 255 <h3><a name="getBytesForPcmSamples"></a><CODE>getBytesForPcmSamples</CODE></h3> 256 <h4>Syntax</h4> 257 <pre class="definition">u32 getBytesForPcmSamples(u32 samples);</pre> 258 <h4>Arguments</h4> 259 <table class="arguments"> 260 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 261 <tbody> 262 <tr> 263 <td>in</td> 264 <th>samples</th> 265 <td>Number of samples.</td> 266 </tr> 267 </tbody> 268 </table> 269 <h4>Return Values</h4> 270 <p>The length (in bytes) of the value specified in the sampling data.</p> 271 <h4>Description</h4> 272 <p><CODE>getBytesForPcmSamples</CODE> returns the number of bytes for copying the specified user application value in the sampling data. 273 </p> 274 275 276 <h3><a name="getSampleForAdpcmNibble"></a><CODE>getSampleForAdpcmNibble</CODE></h3> 277 <h4>Syntax</h4> 278 <pre class="definition">u32 getSampleForAdpcmNibble(u32 nibble);</pre> 279 <h4>Arguments</h4> 280 <table class="arguments"> 281 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 282 <tbody> 283 <tr> 284 <td>in</td> 285 <th>nibble</th> 286 <td>ADPCM nibble offset, including frame headers.</td> 287 </tr> 288 </tbody> 289 </table> 290 <h4>Return Values</h4> 291 <p>The zero-based sample index for the corresponding ADPCM sampling data.</p> 292 <h4>Description</h4> 293 <p><CODE>getSampleForAdpcmNibble</CODE> returns the number of zero-based samples for the corresponding ADPCM nibble.</p> 294 295 <h3><a name="getNibbleAddress"></a><CODE>getNibbleAddress</CODE></h3> 296 <h4>Syntax</h4> 297 <pre class="definition">u32 getNibbleAddress(u32 samples);</pre> 298 <h4>Arguments</h4> 299 <table class="arguments"> 300 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 301 <tbody> 302 <tr> 303 <td>in</td> 304 <th>samples</th> 305 <td>16-bit PCM address offset. <CODE>0</CODE> is the first sample. <CODE>100</CODE> is the 101st sample.</td> 306 </tr> 307 </tbody> 308 </table> 309 <h4>Return Values</h4> 310 <p>Corresponding nibble address.</p> 311 <h4>Description</h4> 312 <p> 313 <CODE>getNibbleAddress</CODE> calculates and returns the nibble corresponding to the sampling data, as based on the offset passed to the argument. </p> 314 <p>For example, the 100th sample (where the count starts at <CODE>0</CODE>) corresponds to the 116th nibble (where the count also starts at <CODE>0</CODE>). Note that the calculated nibble address incorporates the 2-nibble frame header that is already in DSP ADPCM compressed format. 315 </p> 316 <p>One more example: The 0th sample corresponds to a nibble offset of 2, which is the 3rd nibble (counting from 0).</p> 317 318 <h3><a name="getLoopContext"></a><CODE>getLoopContext</CODE></h3> 319 <h4>Syntax</h4> 320 <pre class="definition"> 321typedef struct 322{ 323 // start context 324 s16 coef[16]; 325 u16 gain; 326 u16 pred_scale; 327 s16 yn1; 328 s16 yn2; 329 330 // loop context 331 u16 loop_pred_scale; 332 s16 loop_yn1; 333 s16 loop_yn2; 334} ADPCMINFO; 335 336void getLoopContext( 337 u8 *src, // location of ADPCM buffer in RAM 338 ADPCMINFO *cxt, // location of adpcminfo 339 u32 samples // samples to desired context 340); 341</pre> 342 <h4>Arguments</h4> 343 <table class="arguments"> 344 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 345 <tbody> 346 <tr> 347 <td>in</td> 348 <th>src</th> 349 <td>Pointer to the buffer containing the DSP ADPCM encoded sample.</td> 350 </tr> 351 <tr> 352 <td>out</td> 353 <th>cxt</th> 354 <td>The pointer to the ADPCMINFO structure. The <CODE>getLoopContext</CODE> function places the loop context information inside this structure.</td> 355 </tr> 356 <tr> 357 <td>in</td> 358 <th>samples</th> 359 <td>The offset from the starting position of the loop in the sampling data. This loop starting position is not a nibble address, but rather the raw sample number where the loop starts (in other words, the first sample played in the loop). <br> If the loop begins at the very first sample, the offset is zero. If the loop begins at the 101st sample, the offset is 100.</td> 360 </tr> 361 </tbody> 362 </table> 363 <h4>Return Values</h4> 364 <p>None.</p> 365 <h4>Description</h4> 366 <p><CODE>getLoopContext</CODE> returns the DSP ADPCM loop context, based on the offset in the sample data given to the argument.</p> 367 368 <h3><a name="encode"></a><CODE>encode</CODE></h3> 369 <h4>Syntax</h4> 370 <pre class="definition"> 371typedef struct 372{ 373 // start context 374 s16 coef[16]; 375 u16 gain; 376 u16 pred_scale; 377 s16 yn1; 378 s16 yn2; 379 380 // loop context 381 u16 loop_pred_scale; 382 s16 loop_yn1; 383 s16 loop_yn2; 384} ADPCMINFO; 385 386void encode( 387 s16 *src, // location of source samples (16bit PCM signed little endian) 388 u8 *dst, // location of destination buffer 389 ADPCMINFO *cxt, // location of adpcm info 390 u32 samples // number of samples to encode 391); 392</pre> 393 <h4>Arguments</h4> 394 <table class="arguments"> 395 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 396 <tbody> 397 <tr> 398 <td>in</td> 399 <th>src</th> 400 <td>Pointer to the buffer for signed little-endian 16-bit PCM sampling data.</td> 401 </tr> 402 <tr> 403 <td>out</td> 404 <th>dst</th> 405 <td>The pointer to the buffer where the DSP ADPCM encoded data are output.<br> The application must allocate memory for this buffer. You must calculate the buffer size using <CODE><a href="#getBytesForAdpcmBuffer">getBytesForAdpcmBuffer</a></CODE>.</td> 406 </tr> 407 <tr> 408 <td>in</td> 409 <th>cxt</th> 410 <td>Pointer to the <CODE>ADPCMINFO</CODE> structure. The <CODE>encode</CODE> function stores sampling data coefficients and context information in this structure. <br>Note that a number of parameters (<SPAN class="argument">gain</SPAN>, <SPAN class="argument">yn1</SPAN>, and <SPAN class="argument">yn2</SPAN>) are always <CODE>0</CODE>. <br>Before decoding commences, the corresponding registers in the DSP decoder hardware must be cleared. These parameters are included in the structure to force this to happen. <br>After <CODE>encode</CODE> has been called, the loop context parameters always become <CODE>0</CODE>. To set these values, you must call <CODE><a href="#getLoopContext">getLoopContext</a></CODE> after the sampling data have been looped.</td> 411 </tr> 412 <tr> 413 <td>in</td> 414 <th>samples</th> 415 <td>Number of samples to encode.</td> 416 </tr> 417 </tbody> 418 </table> 419 <h4>Return Values</h4> 420 <p>None.</p> 421 <h4>Description</h4> 422 <p><CODE>encode</CODE> compresses 16-bit PCM data into DSP ADPCM format.</p> 423 424 <h3><a name="decode"></a>decode</h3> 425 <h4>Syntax</h4> 426 <pre class="definition"> 427typedef struct 428{ 429 // start context 430 s16 coef[16]; 431 u16 gain; 432 u16 pred_scale; 433 s16 yn1; 434 s16 yn2; 435 436 // loop context 437 u16 loop_pred_scale; 438 s16 loop_yn1; 439 s16 loop_yn2; 440} ADPCMINFO; 441 442void decode( 443 u8 *src, // location of encoded source samples 444 s16 *dst, // location of destination buffer (16 bits / sample) 445 ADPCMINFO *cxt, // location of adpcm info 446 u32 samples // number of samples to decode 447); 448</pre> 449 <h4>Arguments</h4> 450 <table class="arguments"> 451 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 452 <tbody> 453 <tr> 454 <td>in</td> 455 <th>src</th> 456 <td>Pointer to the buffer containing the DSP ADPCM data.</td> 457 </tr> 458 <tr> 459 <td>out</td> 460 <th>dst</th> 461 <td>Pointer to a buffer that has been allocated for storing the uncompressed PCM data. <br>The size of this buffer is calculated by calling <CODE><a href="#getBytesForPcmBuffer">getBytesForPcmBuffer</a></CODE>.</td> 462 </tr> 463 <tr> 464 <td>in</td> 465 <th>cxt</th> 466 <td>Pointer to the <CODE>ADPCMINFO</CODE> structure.<br> This structure must contain the coefficient and initial state data that corresponds to the sample being decoded.</td> 467 </tr> 468 <tr> 469 <td>in</td> 470 <th>samples</th> 471 <td>Number of samples to decode.</td> 472 </tr> 473 </tbody> 474 </table> 475 <h4>Return Values</h4> 476 <p>None.</p> 477 <h4>Description</h4> 478 <p> 479 <CODE>decode</CODE> is used for decoding DSP ADPCM sample data into signed, little-endian, 16-bit PCM data. 480 </p> 481<!-- テンプレ <h3></h3> <h4>構文</h4> <pre class="definition"></pre> 482 <h4>Arguments</h4> 483 <table class="arguments"> 484 <thead> <tr> <td width="15"> </td><th>Name</th> <td>Description</td> </tr> </thead> 485 <tbody> 486 <tr> 487 <td>in</td> 488 <th></th> 489 <td></td> 490 </tr> 491 </tbody> 492 </table> 493 <h4>Return Values</h4> 494 <h4>Description</h4> 495--> 496 497 </div> 498 499 500 <h2><a name="sampleCode"></a>Sample Code</h2> 501 <p><CODE>WaveCodecCtr.dll</CODE> has been created for use with Win32 applications. This section provides some samples.</p> 502 <ul> 503 <li><a href="#usage_init">Initialization</a></li> 504 <li><a href="#usage_encode">Encoding</a></li> 505 <li><a href="#usage_decode">Decoding</a></li> 506 </ul> 507 508 <div class="subSection"> 509 <h3><a name="usage_init"></a>Initialization</h3> 510 <p>Applications that call DLLs must comply with Win32 rules when calling <CODE>WaveCodecCtr.dll</CODE>. 511 </p> 512<pre class="definition"> 513typedef signed short s16; 514typedef unsigned char u8; 515typedef unsigned short u16; 516typedef unsigned long u32; 517 518/* --------------------------------------------------------------- 519 520 Import the <CODE>WaveCodecCtr.dll</CODE> API. 521 522 ---------------------------------------------------------------- */ 523typedef struct 524{ 525 // start context 526 s16 coef[16]; 527 u16 gain; 528 u16 pred_scale; 529 s16 yn1; 530 s16 yn2; 531 532 // loop context 533 u16 loop_pred_scale; 534 s16 loop_yn1; 535 s16 loop_yn2; 536 537} ADPCMINFO; 538 539static HINSTANCE hDll; 540typedef u32 (*lpFunc1)(u32); 541typedef u32 (*lpFunc2)(void); 542typedef void (*lpFunc3)(s16*, u8*, ADPCMINFO*, u32); 543typedef void (*lpFunc4)(u8*, s16*, ADPCMINFO*, u32); 544typedef void (*lpFunc5)(u8*, ADPCMINFO*, u32); 545lpFunc1 getBytesForAdpcmBuffer; 546lpFunc1 getBytesForAdpcmSamples; 547lpFunc1 getBytesForPcmBuffer; 548lpFunc1 getBytesForPcmSamples; 549lpFunc1 getSampleForAdpcmNibble; 550lpFunc1 getNibbleAddress; 551lpFunc2 getBytesForAdpcmInfo; 552lpFunc3 encode; 553lpFunc4 decode; 554lpFunc5 getLoopContext; 555 556/*--------------------------------------------------------------------------*/ 557void clean_up(void) 558{ 559 if (hDll) 560 FreeLibrary(hDll); 561} 562 563/*--------------------------------------------------------------------------*/ 564int getDll(void) 565{ 566 hDll = LoadLibrary("WaveCodecCtr.dll"); 567 if (hDll) 568 { 569 if (!(getBytesForAdpcmBuffer = 570 (lpFunc1)GetProcAddress( 571 hDll, 572 "getBytesForAdpcmBuffer" 573 ))) return 1; 574 if (!(getBytesForAdpcmSamples = 575 (lpFunc1)GetProcAddress( 576 hDll, 577 "getBytesForAdpcmSamples" 578 ))) return 1; 579 if (!(getBytesForPcmBuffer = 580 (lpFunc1)GetProcAddress( 581 hDll, 582 "getBytesForPcmBuffer" 583 ))) return 1; 584 if (!(getBytesForPcmSamples = 585 (lpFunc1)GetProcAddress( 586 hDll, 587 "getBytesForPcmSamples" 588 ))) return 1; 589 if (!(getNibbleAddress = 590 (lpFunc1)GetProcAddress( 591 hDll, 592 "getNibbleAddress" 593 ))) return 1; 594 if (!(getSampleForAdpcmNibble = 595 (lpFunc1)GetProcAddress( 596 hDll, 597 "getSampleForAdpcmNibble" 598 ))) return 1; 599 if (!(getBytesForAdpcmInfo = 600 (lpFunc2)GetProcAddress( 601 hDll, 602 "getBytesForAdpcmInfo" 603 ))) return 1; 604 if (!(encode = 605 (lpFunc3)GetProcAddress( 606 hDll, 607 "encode" 608 ))) return 1; 609 if (!(decode = 610 (lpFunc4)GetProcAddress( 611 hDll, 612 "decode" 613 ))) return 1; 614 if (!(getLoopContext = 615 (lpFunc5)GetProcAddress( 616 hDll, 617 "getLoopContext" 618 ))) return 1; 619 return(0); 620 } 621 return(1); 622} 623 624 625/*--------------------------------------------------------------------------*/ 626int _tmain(int argc, _TCHAR* argv[]) 627{ 628 if (getDll()) 629 { 630 clean_up(); 631 exit(1); 632 } 633 634 // do stuff here 635 636 clean_up(); 637} 638</pre> 639 640 <h3><a name="usage_encode"></a>Encoding</h3> 641 <p> 642 The encoding function assumes that the data are 16-bit, little endian, PCM data (as used for Windows <CODE>.wav</CODE> files). If you want the application to encode big-endian data, you must flip the endian before encoding.</p> 643 <pre class="definition"> 644//... loaded WaveCodecCtr.dll 645 646//... put some PCM buffer in memory, reverse the endian if you have to 647u8 *adpcm = (u8*)malloc(getBytesForAdpcmBuffer(samplesToEncode)); 648 649if (adpcm) 650{ 651 ADPCMINFO adpcminfo; 652 653 // ok.. lets encode it! 654 encode(source, adpcm, &adpcminfo, samplesToEncode); 655 656 // get ADPCM loop context if sample is looped 657 if (samplesToLoopStart) 658 getLoopContext(adpcm, &adpcminfo, samplesToLoopStart); 659 660 // see how many bytes to store the encoded data stream 661 u32 nBytesToStore = getBytesForAdpcmSamples(samplesToEncode); 662 663 ... store encoded ADPCM data stream to file 664 665 ... store ADPCM context to file 666 667 u32 nibbleStartOffset = getNibbleAddress(0); 668 u32 nibbleLoopStartOffset = getNibbleAddress(samplesToLoopStart); 669 u32 nibbleEndAddress = getNibbleAddress(samplesToEncode); 670 671 ... store nibble addressing to file 672 673 // don't need the ADPCM buffer anymore 674 free(adpcm); 675} 676 677... continue 678 </pre> 679 680 <h3><a name="usage_decode"></a>Decoding</h3> 681 <p> 682 The decoding result is output as 16-bit, little-endian, PCM data. 683 </p> 684 685 <pre class="definition"> 686... loaded WaveCodecCtr.dll 687 688... put some ADPCM buffer and corresponding ADPCMINFO in memory, 689... ADPCM is byte ordered.. not endian sensitive. 690 691s16 *pcm = (u8*)malloc(getBytesForPcmBuffer(samplesToDecode)); 692 693if (pcm) 694{ 695 // Decode 696 decode(source, pcm, adpcminfo, samplesToDecode); 697 698 ... store decoded PCM buffer to file 699 700 // Free the PCM buffer 701 free(pcm); 702} 703 704... continue 705</pre> 706</div> 707 708<h2><a name="caution"></a>Cautions for Encoding and Playing Looped Wave Files</h2> 709<p>Note the following cautions when encoding looped waveforms and when playing them on the actual hardware.</p> 710<p class="warning">The information relating to encoding also pertains to the use of the <CODE>nn::snd::EncodeAdpcmData</CODE> function for encoding data into DSP ADPCM on the actual hardware.</p> 711 712<ul> 713 <li><a href="#caution_loop">How to Play Regular Looped Waveforms</a></li> 714 <li><a href="#caution_align">Align the Loop Start Position to an 8-byte Boundary</a></li> 715 <li><a href="#caution_loopStart">Noise When the Loop Start Equals the Start of the Waveform</a></li> 716 <li><a href="#caution_loopEnd">Noise When the Loop End Equals the End of the Waveform</a></li> 717</ul> 718 719<div class="subSection"> 720<h3><a name="caution_loop"></a>How to Play Regular Looped Waveforms</h3> 721<p>When looping a waveform like the following on the actual hardware:</p> 722<pre class="definition"> 723 WS LS LE 724 |-------|<-------------------->| 725 726 WS: Start of waveform 727 LS: Loop start position 728 LE: Loop end position 729</pre> 730<ol> 731 <li><CODE>WaveBuffer</CODE> for playing WS to LE</li> 732 <li><CODE>WaveBuffer</CODE> for playing LS to LE</li> 733</ol> 734<p>Prepare two <CODE>WaveBuffer</CODE> instances (as shown) and set the order as 1. → 2. in <CODE>nn::snd::Voice</CODE>.</p> 735 736 737<pre class="definition"> 738 WS LE 739 1. |------------------------------| (When the loopFlag of WaveBuffer is false.) 740 741 LS LE 742 2. |<-------------------->| (When the loopFlag of WaveBuffer is true.) 743</pre> 744 745<h3><a name="caution_align"></a>Align the Loop Start Position to an 8-byte Boundary</h3> 746<p>In the DSP ADPCM format, 8 bytes (corresponding to 14 samples) are handled as one set of information. For this reason, the <SPAN class="argument">bufferAddress</SPAN> argument of the <CODE>nn::snd::WaveBuffer</CODE> function must specify an address with an 8-byte boundary.</p> 747<p>On the other hand, when creating <a href="#caution_loop"><CODE>WaveBuffer</CODE> as described in 2</a>, LS is not necessarily at an 8-byte (14-sample) boundary.</p> 748<p>If the boundary is not 8 bytes (14 samples), you must displace the LS position to an 8-byte boundary so this restriction is satisfied.</p> 749<p>For example, if LS is at the 16th sample, you could slide it to the next 14-sample boundary (28 samples) and top off the waveforms after LE with the moved part before encoding.</p> 750 751<pre class="definition"> 752 LS LE 753 |<----------------->| 754 ^^^^ 755 ↓ 756 LS' LE' 757 ----|<------------------->| 758 ^^^^ 759</pre> 760 761 762<h3><a name="caution_loopStart"></a>Noise When the Loop Start Equals the Start of the Waveform</h3> 763<p>Because of encoder limitations, when the loop start position equals the start of a waveform, you cannot play a clean loop without noise.</p> 764<p>If the loop start position equals the start of the waveform, use the technique described in <a href="#caution_align">Align the loop start position to an 8-byte boundary</a> to slide LS' to 14, so you can play the loop cleanly without noise. 765</p> 766 767<h3><a name="caution_loopEnd"></a>Noise When the Loop End Equals the End of the Waveform</h3> 768<p>Because of encoder limitations, when the loop start position equals the end of a waveform, encoding is not stable and noise occurs.</p> 769<p>When waveforms continue beyond LE, for the <SPAN class="argument">samples</SPAN> argument of the <CODE><a href="#encode">encode</a></CODE> function, pass <CODE>WS to end of waveform</CODE> rather than <CODE>WS to LE</CODE>. 770</p> 771<pre class="definition"> 772 WS LS LE WE 773 |-------|<-------------------->|----| 774 775 WS: Start of waveform 776 WE : End of waveform 777 LS: Loop start position 778 LE: Loop end position 779 780 encode( WS address, dst, cxt, WE-WS ); 781</pre> 782 783<p>When waveforms do not continue beyond LE, apply the technique introduced in <a href="#caution_align">Align the loop start position to an 8-byte boundary</a> to use copied waveforms for about 100 samples from LS, and position them after LE.</p> 784<pre class="definition"> 785 WS LS LE=WE 786 |-------|<-------------------->| 787 ^^^^^ 788 ↓ 789 WS LS LE WE' 790 |-------|<-------------------->|----| 791 ^^^^^ 792 793 encode( WS address, dst, cxt, WE'-WS ); 794</pre> 795 796 797</div> 798 799 <h2><a name="history"></a>Revision History</h2> 800 <dl class="history"> 801 <dt>2011/12/12</dt> 802 <dd>Initial version.<br /> 803 </dd> 804 </dl> 805 <hr><p>CONFIDENTIAL</p></body> 806</html>