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>Table of Contents</h2> 156 <ul> 157 <li><a href="#overview">Overview</a> 158 <li><a href="#api">Exported Functions</a> 159 <li><a href="#sampleCode">Sample Code</a> 160 <li><a href="#caution">Precautions for Encoding and Playing Back Looped Wave Files</a> 161 <li><a href="#history">Revision History</a> 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 is a single-threaded DLL. 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.</h4> 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. (See <CODE><a href="#getBytesForAdpcmSamples">getBytesForAdpcmSamples</a></CODE> below.)</p> 212 <p> 213 Use this function before you conduct encoding, in order to secure memory for storing the encoding 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 will need to 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>The offset for the ADPCM nibble in the frame header.</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>The 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> Therefore, when the loop starts from the first sample, the offset is <CODE>0</CODE>. If the loop starts from the 101st sample, then the offset is <CODE>100</CODE>.</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>This is the pointer to the buffer where the DSP ADPCM encoded data are output.<br> The application needs to allocate memory for this buffer. You need to 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 (<CODE>gain</CODE>, <CODE>yn1</CODE>, <CODE>yn2</CODE>) 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 in order 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 need to 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>The 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 the buffer secured for storing the decoded 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 coefficients and data in the initial state corresponding to the sampling data being decoded.</td> 467 </tr> 468 <tr> 469 <td>in</td> 470 <th>samples</th> 471 <td>The 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> <h4>引数</h4> <table class="arguments"> <thead> <tr> <td width="15"> </td><th>名前</th> <td>説明</td> </tr> </thead> <tbody> <tr> <td>in</td> <th></th> <td></td> </tr> </tbody> </table> <h4>返り値</h4> <h4>説明</h4> --> 482 483 </div> 484 485 486 <h2><a name="sampleCode"></a>Sample Code</h2> 487 <p><CODE>WaveCodecCtr.dll</CODE> has been created for use with Win32 applications. A number of samples are given below.</p> 488 <ul> 489 <li><a href="#usage_init">Initialization</a></li> 490 <li><a href="#usage_encode">Encoding</a></li> 491 <li><a href="#usage_decode">Decoding</a></li> 492 </ul> 493 494 <div class="subSection"> 495 <h3><a name="usage_init"></a>Initialization</h3> 496 <p>Applications that call DLLs must comply with Win32 rules when calling <CODE>WaveCodecCtr.dll</CODE>. 497 </p> 498<pre class="definition"> 499typedef signed short s16; 500typedef unsigned char u8; 501typedef unsigned short u16; 502typedef unsigned long u32; 503 504/* --------------------------------------------------------------- 505 506 Import the <CODE>WaveCodecCtr.dll</CODE> API 507 508 ---------------------------------------------------------------- */ 509typedef struct 510{ 511 // start context 512 s16 coef[16]; 513 u16 gain; 514 u16 pred_scale; 515 s16 yn1; 516 s16 yn2; 517 518 // loop context 519 u16 loop_pred_scale; 520 s16 loop_yn1; 521 s16 loop_yn2; 522 523} ADPCMINFO; 524 525static HINSTANCE hDll; 526typedef u32 (*lpFunc1)(u32); 527typedef u32 (*lpFunc2)(void); 528typedef void (*lpFunc3)(s16*, u8*, ADPCMINFO*, u32); 529typedef void (*lpFunc4)(u8*, s16*, ADPCMINFO*, u32); 530typedef void (*lpFunc5)(u8*, ADPCMINFO*, u32); 531lpFunc1 getBytesForAdpcmBuffer; 532lpFunc1 getBytesForAdpcmSamples; 533lpFunc1 getBytesForPcmBuffer; 534lpFunc1 getBytesForPcmSamples; 535lpFunc1 getSampleForAdpcmNibble; 536lpFunc1 getNibbleAddress; 537lpFunc2 getBytesForAdpcmInfo; 538lpFunc3 encode; 539lpFunc4 decode; 540lpFunc5 getLoopContext; 541 542/*--------------------------------------------------------------------------*/ 543void clean_up(void) 544{ 545 if (hDll) 546 FreeLibrary(hDll); 547} 548 549/*--------------------------------------------------------------------------*/ 550int getDll(void) 551{ 552 hDll = LoadLibrary("WaveCodecCtr.dll"); 553 if (hDll) 554 { 555 if (!(getBytesForAdpcmBuffer = 556 (lpFunc1)GetProcAddress( 557 hDll, 558 "getBytesForAdpcmBuffer" 559 ))) return 1; 560 if (!(getBytesForAdpcmSamples = 561 (lpFunc1)GetProcAddress( 562 hDll, 563 "getBytesForAdpcmSamples" 564 ))) return 1; 565 if (!(getBytesForPcmBuffer = 566 (lpFunc1)GetProcAddress( 567 hDll, 568 "getBytesForPcmBuffer" 569 ))) return 1; 570 if (!(getBytesForPcmSamples = 571 (lpFunc1)GetProcAddress( 572 hDll, 573 "getBytesForPcmSamples" 574 ))) return 1; 575 if (!(getNibbleAddress = 576 (lpFunc1)GetProcAddress( 577 hDll, 578 "getNibbleAddress" 579 ))) return 1; 580 if (!(getSampleForAdpcmNibble = 581 (lpFunc1)GetProcAddress( 582 hDll, 583 "getSampleForAdpcmNibble" 584 ))) return 1; 585 if (!(getBytesForAdpcmInfo = 586 (lpFunc2)GetProcAddress( 587 hDll, 588 "getBytesForAdpcmInfo" 589 ))) return 1; 590 if (!(encode = 591 (lpFunc3)GetProcAddress( 592 hDll, 593 "encode" 594 ))) return 1; 595 if (!(decode = 596 (lpFunc4)GetProcAddress( 597 hDll, 598 "decode" 599 ))) return 1; 600 if (!(getLoopContext = 601 (lpFunc5)GetProcAddress( 602 hDll, 603 "getLoopContext" 604 ))) return 1; 605 return(0); 606 } 607 return(1); 608} 609 610 611/*--------------------------------------------------------------------------*/ 612int _tmain(int argc, _TCHAR* argv[]) 613{ 614 if (getDll()) 615 { 616 clean_up(); 617 exit(1); 618 } 619 620 // do stuff here 621 622 clean_up(); 623} 624</pre> 625 626 <h3><a name="usage_encode"></a>Encoding</h3> 627 <p> 628 The encoding function assumes that the data are 16-bit little-endian PCM data (as used for Windows WAV files). If you want the application to encode big-endian data, you will need to flip the endianness before encoding.</p> 629 <pre class="definition"> 630//... loaded WaveCodecCtr.dll 631 632//... put some PCM buffer in memory, reverse the endian if you have to 633u8 *adpcm = (u8*)malloc(getBytesForAdpcmBuffer(samplesToEncode)); 634 635if (adpcm) 636{ 637 ADPCMINFO adpcminfo; 638 639 // ok.. lets encode it! 640 encode(source, adpcm, &adpcminfo, samplesToEncode); 641 642 // get ADPCM loop context if sample is looped 643 if (samplesToLoopStart) 644 getLoopContext(adpcm, &adpcminfo, samplesToLoopStart); 645 646 // see how many bytes to store the encoded data stream 647 u32 nBytesToStore = getBytesForAdpcmSamples(samplesToEncode); 648 649 ... store encoded ADPCM data stream to file 650 651 ... store ADPCM context to file 652 653 u32 nibbleStartOffset = getNibbleAddress(0); 654 u32 nibbleLoopStartOffset = getNibbleAddress(samplesToLoopStart); 655 u32 nibbleEndAddress = getNibbleAddress(samplesToEncode); 656 657 ... store nibble addressing to file 658 659 // don't need the ADPCM buffer anymore 660 free(adpcm); 661} 662 663... continue 664 </pre> 665 666 <h3><a name="usage_decode"></a>Decoding</h3> 667 <p> 668 The decoding result is output as 16-bit little-endian PCM data. 669 </p> 670 671 <pre class="definition"> 672... loaded WaveCodecCtr.dll 673 674... put some ADPCM buffer and corresponding ADPCMINFO in memory, 675... ADPCM is byte ordered.. not endian sensitive. 676 677s16 *pcm = (u8*)malloc(getBytesForPcmBuffer(samplesToDecode)); 678 679if (pcm) 680{ 681 // ok.. lets decode it! 682 decode(source, pcm, adpcminfo, samplesToDecode); 683 684 ... store decoded PCM buffer to file 685 686 // don’t need the PCM buffer anymore 687 free(pcm); 688} 689 690... continue 691</div> 692 693<h2><a name="caution"></a>Precautions for Encoding and Playing Back Looped Wave Files</h2> 694<p> 695The following precautions should be noted when encoding looped waveforms and when playing them back on the actual hardware.</p> 696<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. 697</p> 698 699<ul> 700 <li><a href="#caution_loop">How to play regular looped waveforms</a></li> 701 <li><a href="#caution_align">Align the loop start position to an 8-byte boundary</a></li> 702 <li><a href="#caution_loopStart">There is noise when loop start = start of waveform </a></li> 703 <li><a href="#caution_loopEnd">There is noise when loop end = end of waveform </a></li> 704</ul> 705 706<div class="subSection"> 707<h3><a name="caution_loop"></a>How to play regular looped waveforms</h3> 708<p>When looping a waveform like the one shown below on the actual hardware: 709<pre class="definition"> 710 WS LS LE 711 |-------|<-------------------->| 712 713 WS : Start of waveform 714 LS : Loop start position 715 LE : Loop end position 716</pre> 717<ol> 718 <li><CODE>WaveBuffer</CODE> for playing WS to LE</li> 719 <li><CODE>WaveBuffer</CODE> for playing LS to LE</li> 720</ol> 721<p>Prepare two <CODE>WaveBuffer</CODE> (as shown above) and set the order as 1. → 2. in <CODE>nn::snd::Voice</CODE>.</p> 722 723 724<pre class="definition"> 725 WS LE 726 1. |------------------------------| (When <CODE>WaveBuffer</CODE> loopFlag is false) 727 728 LS LE 729 2. |<-------------------->| (When <CODE>WaveBuffer</CODE> loopFlag is true) 730</pre> 731 732<h3><a name="caution_align"></a>Align the loop start position to an 8-byte boundary</h3> 733<p>In the DSP ADPCM format, 8 bytes (corresponding to 14 samples) are handled as one set of information. 734 735For 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. 736</p> 737<p>On the other hand, when creating <a href="#caution_loop"><CODE>WaveBuffer</CODE> as described in 2. above</a>, LS is not necessarily at an 8-byte (14-sample) boundary. 738</p> 739<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. 740</p> 741<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. 742</p> 743 744<pre class="definition"> 745 LS LE 746 |<----------------->| 747 ^^^^ 748 ↓ 749 LS' LE' 750 ----|<------------------->| 751 ^^^^ 752</pre> 753 754 755<h3><a name="caution_loopStart"></a>There is noise when loop start = start of waveform </h3> 756<p>Due to encoder limitations, when the loop start position equals the start of a waveform, you cannot play a clean loop without noise. 757</p> 758<p>If the loop start position is at the start of the waveform, apply the technique described in "<a href="#caution_align">Align the loop start position to an 8-byte boundary</a>" to slide <CODE>LS'</CODE> to 14 so you can play the loop cleanly without noise. 759 760 761 762</p> 763 764<h3><a name="caution_loopEnd"></a>There is noise when loop end = end of waveform </h3> 765<p>Due to encoder limitations, when the loop start position equals the end of a waveform, encoding is not stable and noise occurs. 766</p> 767<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 "WS to end of waveform" rather than "WS to LE." 768 769 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>If 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 copy the waveforms for about 100 samples from LS and position them after LE. 784 785 786 </p> 787<pre class="definition"> 788 WS LS LE=WE 789 |-------|<-------------------->| 790 ^^^^^ 791 ↓ 792 WS LS LE WE' 793 |-------|<-------------------->|----| 794 ^^^^^ 795 796 encode( WS address, dst, cxt, WE'-WS ); 797</pre> 798 799 800 801</div> 802 803 <h2><a name="history"></a>Revision History</h2> 804 <dl class="history"> 805 <dt>2011/12/12</dt> 806 <dd>Initial version.<br /> 807 </dd> 808 </dl> 809 <hr><p>CONFIDENTIAL</p></body> 810</html>