home *** CD-ROM | disk | FTP | other *** search
/ Pleasure 76 / OTACD76.bin / archive / game / PsrSDK16a / PsrSDK16a.lzh / Sample / PsrFF8 / Plugin.c < prev   
C/C++ Source or Header  |  2000-10-29  |  18KB  |  605 lines

  1. /******************************************************************************/
  2. /*                                          */
  3. /* [PSストリームアクセスプラグイン]                          */
  4. /*                                          */
  5. /*    FILE NAME    : Plugin.c                             */
  6. /*    FUNCTION    : FF8ムービー処理                      */
  7. /*                                          */
  8. /*    FUNCTIONS        | an outline                      */
  9. /*    --------------------------+-------------------------------------------- */
  10. /*    PsrQueryPlugin()    | プラグイン情報の取得                  */
  11. /*    PsrIsSupportCDBegin()    | CDサポート判定 開始処理              */
  12. /*    PsrIsSupportCDEnd()    | CDサポート判定 終了処理              */
  13. /*    PsrIsSupportCDSector()    | CDサポート判定 セクタ通知              */
  14. /*    PsrIsSupportCDResult()    | CDサポート判定 結果取得              */
  15. /*    PsrGetStrDataInfo()    | ストリームデータ情報の取得              */
  16. /*    PsrOpenCD()        | CDストリームのオープン              */
  17. /*    PsrClose()        | ストリームデータのクローズ              */
  18. /*    PsrRead()        | ストリームデータの読み取り              */
  19. /*    PsrSeek()        | 読み取り位置の設定                  */
  20. /*    PsrDecodeAudio()    | 音声データのデコード                  */
  21. /*                                          */
  22. /*    HISTORY        | Comment                | Name          */
  23. /*    ------------------+---------------------------------------+------------ */
  24. /*    2000.06.12    | 新規作成                | ふぃろ      */
  25. /*    2000.07.11    | PSRPLUGIN構造体の変更        1.10    | ふぃろ      */
  26. /*    2000.07.12    | CD解析中断用処理の追加    1.10    | ふぃろ      */
  27. /*    2000.08.08    | プラグイン仕様変更        1.20    | ふぃろ      */
  28. /*    2000.08.13    | 最終フレーム取得不能対策    1.21    | ふぃろ      */
  29. /*    2000.10.28    | プラグイン仕様変更        1.30    | ふぃろ      */
  30. /*                                          */
  31. /*            (C) Copyright ふぃろ 2000. All rights reserved.       */
  32. /******************************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <string.h>
  36. #include <malloc.h>
  37. #include <Windows.h>
  38.  
  39. #include "CdAccess.h"
  40. #include "PSRP.h"
  41.  
  42.  
  43. typedef struct {    // セクター構造 ----------------------------------------
  44.     BYTE        acCdxa[24];        // CD-ROM XA
  45.     BYTE        abHead[4];        // SM*\1
  46.     BYTE        bSectNo;        // セクタ番号    0~
  47.     BYTE        bLastSectNo;        // フレーム内最終セクタ番号
  48.     USHORT        usFrameNo;        // フレーム番号    0~
  49.     BYTE        abData[2040];        // データ
  50.     BYTE        abEdc[4];        // EDC
  51.     BYTE        abPParity[172];        // Pパリティ
  52.     BYTE        abQParity[104];        // Qパリティ
  53. } _TSECTOR, *_PTSECTOR;
  54.  
  55.  
  56. typedef struct {    // ストリーム情報 --------------------------------------
  57.     WORD        wTypeFlags;    // データ種別フラグ    PSR_STRTYPE_XXX
  58.     WORD        wNumFrame;    // フレーム数
  59.     WORD        wUSector;    // フレーム当りのセクタ数
  60.     DWORD        dwBeginningPos;    // データ開始セクタ番号
  61. } _TSTREAM, *_PTSTREAM;
  62.  
  63.  
  64. typedef struct {    // ストリーム探索ハンドルの内容 ------------------------
  65.     BOOL        fFindout;    // 発見フラグ
  66.     INT        iBuffer;    // ストリームバッファ数
  67.     INT        iNum;        // ストリーム数
  68.     _PTSTREAM    pstr;        // ストリーム情報群
  69. } _TFIND, *_PTFIND;
  70.  
  71.  
  72. typedef struct {    // ストリームハンドルの内容 ----------------------------
  73.     HANDLE        hCdrom;        // CD-ROMハンドル
  74.     DWORD        nBeginning;    // ストリーム開始位置
  75.     DWORD        nNumSector;    // 残りセクタ数
  76.     WORD        wNumFrame;    // フレーム数
  77.     WORD        wSectPerFrame;    // フレーム当りのセクタ数
  78.     _PTSECTOR    psector;    // 退避セクタ
  79. } _THANDLE, *_PTHANDLE;
  80.  
  81.  
  82. typedef struct {    // WAVE要素 --------------------------------------------
  83.     SHORT        sLeft;
  84.     SHORT        sRight;
  85. } _WAVEELM, *_PWAVEELM;
  86.  
  87.  
  88.             // ADPCM用係数 -----------------------------------------
  89. static INT    aiFILTER0[] = {0x0000, 0x00f0, 0x01cc, 0x0188, 0x01e8 };
  90. static INT    aiFILTER1[] = {0x0000, 0x0000, -0x00d0, -0x00dc, -0x00f0 };
  91.  
  92. #define _ROUND(val)    (min(0x7fffL, max(-0x8000L, val)))
  93.  
  94. /******************************************************************************/
  95. /*                                          */
  96. /*    PsrQueryPlugin() : プラグイン情報の取得                      */
  97. /*                                          */
  98. /******************************************************************************/
  99.  
  100. CEXPORT    VOID    PsrQueryPlugin(
  101.     LPPSRPLUGIN    lpPlugin)    // プラグイン情報取得バッファアドレス
  102. {
  103.     strcpy(lpPlugin->aName,      "FF8 Stream");
  104.     strcpy(lpPlugin->aCopyright, "Copyright (c) Fyiro 2000.");
  105.     lpPlugin->usVersion         = 130;            // 1.10
  106.     lpPlugin->usIsSupportVersion = 0;            // 1.10
  107.     lpPlugin->usSystemVersion    = PSR_SYSTEMVERSION;    // 1.10
  108.     strcpy(lpPlugin->aSiteName, "Fyiro's Garage");        // 1.30
  109.     strcpy(lpPlugin->aSiteUrl, "http://homepage2.nifty.com/~mkb/");    // 1.30
  110. }
  111.  
  112.  
  113.  
  114. /******************************************************************************/
  115. /*                                          */
  116. /*    PsrIsSupportCDBegin() : CDサポート判定 開始処理                  */
  117. /*                                          */
  118. /******************************************************************************/
  119.  
  120. CEXPORT HANDLE    PsrIsSupportCDBegin(
  121.     INT        iNumToc,    // TOCの数
  122.     LPTOCENTRY    lptoc)        // TOC
  123. {
  124.     _PTFIND        pfind;
  125.  
  126.  
  127.     if(iNumToc != 1)        return NULL;
  128.     if(!(lptoc[0].bAdr & 0x04))    return NULL;    // CD-DA
  129.  
  130.     if(!(pfind = malloc(sizeof(_TFIND))))    return NULL;
  131.  
  132.             // ハンドルの作成と初期設定 ----------------------------
  133.     pfind->fFindout    = FALSE;
  134.     pfind->iBuffer    = 10;
  135.     pfind->iNum    = 0;
  136.     pfind->pstr    = malloc(sizeof(_TSTREAM) * pfind->iBuffer);
  137.     if(!pfind->pstr) {
  138.         free(pfind);
  139.         return NULL;
  140.     }
  141.     return pfind;
  142. }
  143.  
  144.  
  145.  
  146. /******************************************************************************/
  147. /*                                          */
  148. /*    PsrIsSupportCDEnd() : CDサポート判定 終了処理                  */
  149. /*                                          */
  150. /******************************************************************************/
  151.  
  152. CEXPORT    VOID    PsrIsSupportCDEnd(
  153.     HANDLE        hIsCD)        // CDサポート判定ハンドル
  154. {
  155.     _PTFIND        pfind;
  156.  
  157.  
  158.     if(!(pfind = hIsCD))    return;
  159.     free(pfind->pstr);
  160.     free(pfind);
  161. }
  162.  
  163. /******************************************************************************/
  164. /*                                          */
  165. /*    PsrIsSupportCDSector() : CDサポート判定 セクタ通知              */
  166. /*                                          */
  167. /******************************************************************************/
  168.  
  169. CEXPORT    BOOL    PsrIsSupportCDSector(
  170.     HANDLE        hIsCD,        // CDサポート判定ハンドル
  171.     TOCENTRY    toc,        // TOC
  172.     DWORD        nSector,    // セクタ番号
  173.     PVOID        pvSector)    // セクタ
  174. {
  175.     _PTFIND        pfind;
  176.     _PTSECTOR    psector;
  177.     _PTSTREAM    pstr;
  178.     BOOL        fStream, fBegin;
  179.  
  180.  
  181.     if(!(pfind = hIsCD))    return FALSE;
  182.     if(!(psector = pvSector)) {                    // 1.10
  183.         if(pfind->fFindout) {                    // 1.10
  184.             pfind->fFindout = FALSE;            // 1.10
  185.             pfind->iNum --;                    // 1.10
  186.         }                            // 1.10
  187.         return FALSE;                        // 1.10
  188.     }                                // 1.10
  189.  
  190.  
  191.     fStream = FALSE;// ストリームのセクタか? -------------------------------
  192.     if(memcmp(psector->abHead, "SM", 2) == 0) {
  193.         if(psector->abHead[3] == 1) {
  194.             if(psector->bLastSectNo) {
  195.                 fStream = TRUE;
  196.             }
  197.         }
  198.     }
  199.  
  200.     fBegin = FALSE;    // 先頭セクタか? ---------------------------------------
  201.     if(fStream && !psector->bSectNo && !psector->usFrameNo) {
  202.         fBegin = TRUE;
  203.     }
  204.  
  205.     if(!pfind->fFindout && !fBegin)    fStream = FALSE;
  206.  
  207. // ストリームが発見されている場合 **********************************************
  208.  
  209.     if(pfind->fFindout) {
  210.         pstr = &pfind->pstr[pfind->iNum - 1];
  211.  
  212.         if(!fStream || fBegin) {
  213.             pfind->fFindout = FALSE;     // 終わり!
  214.             if(!pstr->wNumFrame)    pfind->iNum --;
  215.         }
  216.         else {
  217.             if(psector->bSectNo == psector->bLastSectNo) {
  218.                 pstr->wNumFrame = psector->usFrameNo + 1;
  219.             }
  220.             if(psector->abHead[2] == 'J') {
  221.                 pstr->wTypeFlags |= PSR_STRTYPE_MOVIE;
  222.             }
  223.         }
  224.     }
  225.  
  226. // ストリームが発見されていない場合 ********************************************
  227.  
  228.     if(!pfind->fFindout && fBegin) {
  229.  
  230.             // ストリームが見つかった! -----------------------------
  231.         if(pfind->iBuffer == pfind->iNum) {
  232.             pfind->iBuffer += 10;
  233.             pstr = realloc(pfind->pstr,
  234.                     sizeof(_TSTREAM) * pfind->iBuffer);
  235.             if(!pstr) {
  236.                 pfind->iBuffer -= 10;
  237.                 return TRUE;    // とりあえず正常終了
  238.             }
  239.             pfind->pstr = pstr;
  240.         }
  241.  
  242.         pstr = &pfind->pstr[pfind->iNum];
  243.         pstr->wTypeFlags    = PSR_STRTYPE_AUDIO;
  244.         pstr->wNumFrame        = 0;    // 初期値
  245.         pstr->wUSector        = psector->bLastSectNo + 1;
  246.         pstr->dwBeginningPos    = nSector;
  247.         pfind->fFindout    = TRUE;
  248.         pfind->iNum ++;
  249.     }
  250.  
  251.     return TRUE;
  252. }
  253.  
  254. /******************************************************************************/
  255. /*                                          */
  256. /*    PsrIsSupportCDResult() : CDサポート判定 結果取得              */
  257. /*                                          */
  258. /******************************************************************************/
  259.  
  260. CEXPORT    INT    PsrIsSupportCDResult(
  261.     HANDLE        hIsCD,        // CDサポート判定ハンドル
  262.     INT        iIndex,        // ストリームインデックス
  263.     LPPSRSTREAMINFO    lpStreamInfo)    // ストリームデータ情報
  264. {
  265.     _PTFIND        pfind;
  266.     _PTSTREAM    pstr;
  267.  
  268.  
  269.     if(!(pfind = hIsCD))        return 0;
  270.     if(pfind->iNum <= iIndex)    return -1;
  271.  
  272.     if(lpStreamInfo) {
  273.         pstr = &pfind->pstr[iIndex];
  274.         lpStreamInfo->wTypeFlags    = pstr->wTypeFlags;
  275.         lpStreamInfo->wReserved        = 0;
  276.         lpStreamInfo->nBeginSector    = pstr->dwBeginningPos;
  277.         lpStreamInfo->nNumSector    = (DWORD)pstr->wNumFrame *
  278.                             (DWORD)pstr->wUSector;
  279.         lpStreamInfo->nNumFrame        = (DWORD)pstr->wNumFrame;
  280.         lpStreamInfo->nPlayTime        = ((DWORD)pstr->wNumFrame * 1000) / 15;
  281.         lpStreamInfo->szFrame.cx    = 0x140;
  282.         lpStreamInfo->szFrame.cy    = 0x0e0;
  283.         lpStreamInfo->wFrameRate    = 150;
  284.         lpStreamInfo->wFormatTag    = WAVE_FORMAT_PCM;
  285.         lpStreamInfo->wChannels        = 2;
  286.         lpStreamInfo->wBitsPerSample    = 16;
  287.         lpStreamInfo->nSamplesPerSec    = 44100;
  288.         lpStreamInfo->nDataSize        = lpStreamInfo->nNumSector * 2040;    // 1.30
  289.     }
  290.  
  291.     return pfind->iNum;
  292. }
  293.  
  294. /******************************************************************************/
  295. /*                                          */
  296. /*    PsrGetStrDataInfo() : ストリームデータ情報の取得              */
  297. /*                                          */
  298. /******************************************************************************/
  299.  
  300. CEXPORT    BOOL    PsrGetStrDataInfo(
  301.     INT        iDriveNo,    // ドライブ番号
  302.     DWORD        dwBegin,    // 開始セクタ番号
  303.     DWORD        dwNumSector,    // セクタ数
  304.     LPPSRSTREAMINFO    lpStreamInfo)    // ストリームデータ情報
  305. {
  306.     HANDLE        hCdrom;
  307.     _PTSECTOR    psector;
  308.     INT        iSectPerFrame;
  309.     WORD        wTypeFlags;
  310.  
  311.             // 先頭のセクタだけ読み取る ----------------------------
  312.     hCdrom = CdReadOpen(iDriveNo, NULL, dwBegin, 4, -1);
  313.     if(!hCdrom)    return FALSE;
  314.  
  315.     iSectPerFrame    = 0;
  316.     wTypeFlags    = 0;
  317.     while(psector = CdReadSector(hCdrom, NULL)) {
  318.         if(memcmp(psector->abHead, "SM", 2) == 0 &&
  319.            psector->abHead[3] == 1 && psector->bLastSectNo) {
  320.             iSectPerFrame = psector->bLastSectNo + 1;
  321.             if(psector->abHead[2] == 'N' ||
  322.                psector->abHead[2] == 'R')
  323.                 wTypeFlags |= PSR_STRTYPE_AUDIO;
  324.             else if(psector->abHead[2] == 'J')
  325.                 wTypeFlags |= PSR_STRTYPE_MOVIE;
  326.         }
  327.         CdUnlockReadBuffer(hCdrom, psector);
  328.     }
  329.     CdReadClose(hCdrom);
  330.     if(!iSectPerFrame || !wTypeFlags)    return FALSE;
  331.  
  332.             // ストリームデータ情報を作成する ----------------------
  333.     lpStreamInfo->wTypeFlags    = wTypeFlags;
  334.     lpStreamInfo->wReserved        = 0;
  335.     lpStreamInfo->nBeginSector    = dwBegin;
  336.     lpStreamInfo->nNumSector    = dwNumSector;
  337.     lpStreamInfo->nNumFrame        = dwNumSector / iSectPerFrame;
  338.     lpStreamInfo->nPlayTime        = (lpStreamInfo->nNumFrame * 1000) / 15;
  339.     if(wTypeFlags & PSR_STRTYPE_MOVIE) {
  340.         lpStreamInfo->szFrame.cx    = 0x140;
  341.         lpStreamInfo->szFrame.cy    = 0x0e0;
  342.         lpStreamInfo->wFrameRate    = 150;
  343.     } else {
  344.         lpStreamInfo->szFrame.cx    = 0;
  345.         lpStreamInfo->szFrame.cy    = 0;
  346.         lpStreamInfo->wFrameRate    = 0;
  347.     }
  348.     if(wTypeFlags & PSR_STRTYPE_AUDIO) {
  349.         lpStreamInfo->wFormatTag    = WAVE_FORMAT_PCM;
  350.         lpStreamInfo->wChannels        = 2;
  351.         lpStreamInfo->wBitsPerSample    = 16;
  352.         lpStreamInfo->nSamplesPerSec    = 44100;
  353.     } else {
  354.         lpStreamInfo->wFormatTag    = 0;
  355.         lpStreamInfo->wChannels        = 0;
  356.         lpStreamInfo->wBitsPerSample    = 0;
  357.         lpStreamInfo->nSamplesPerSec    = 0;
  358.     }
  359.     lpStreamInfo->nDataSize        = lpStreamInfo->nNumSector * 2040;//1.30
  360.     return TRUE;
  361. }
  362.  
  363. /******************************************************************************/
  364. /*                                          */
  365. /*    PsrOpenCD() : CDストリームのオープン                      */
  366. /*                                          */
  367. /******************************************************************************/
  368.  
  369. CEXPORT HANDLE    PsrOpenCD(
  370.     INT        iDriveNo,    // ドライブ番号
  371.     LPPSRSTREAMINFO    lpStreamInfo)    // ストリームデータ情報
  372. {
  373.     _PTHANDLE    phandle;
  374.     HANDLE        hCdrom;
  375.  
  376.  
  377.             // CD-ROMのオープン ------------------------------------
  378.     hCdrom = CdReadOpen(iDriveNo, NULL,
  379.                 lpStreamInfo->nBeginSector,
  380.                 lpStreamInfo->nNumSector, -1);
  381.     if(!hCdrom)    return NULL;
  382.  
  383.             // ハンドルを作成 --------------------------------------
  384.     if(!(phandle = malloc(sizeof(_THANDLE)))) {
  385.         CdReadClose(hCdrom);
  386.         return NULL;
  387.     }
  388.     phandle->hCdrom        = hCdrom;
  389.     phandle->nBeginning    = lpStreamInfo->nBeginSector;
  390.     phandle->wSectPerFrame    = (WORD)(lpStreamInfo->nNumSector /
  391.                         lpStreamInfo->nNumFrame);
  392.     phandle->wNumFrame    = (WORD)lpStreamInfo->nNumFrame;
  393.     phandle->psector    = NULL;
  394.     PsrDecodeAudio(NULL, NULL, 0);
  395.  
  396.     return phandle;
  397. }
  398.  
  399. /******************************************************************************/
  400. /*                                          */
  401. /*    PsrClose() : ストリームデータのクローズ                      */
  402. /*                                          */
  403. /******************************************************************************/
  404.  
  405. CEXPORT BOOL    PsrClose(
  406.     HANDLE        hStream)    // ストリームハンドル
  407. {
  408.     _PTHANDLE    phandle;
  409.  
  410.  
  411.     phandle = hStream;
  412.     if(phandle->hCdrom)    CdReadClose(phandle->hCdrom);
  413.     free(phandle);
  414.     return TRUE;
  415. }
  416.  
  417. /******************************************************************************/
  418. /*                                          */
  419. /*    PsrRead() : ストリームデータの読み取り                      */
  420. /*                                          */
  421. /******************************************************************************/
  422.  
  423. CEXPORT BOOL    PsrRead(
  424.     HANDLE        hStream,    // ストリームハンドル
  425.     LPPSRREADBUFF    lpBuffer)    // 読み取りバッファ
  426. {
  427.     _PTHANDLE    phandle;
  428.     _PTSECTOR    psector;
  429.     INT        iPos, iSize;
  430.     PBYTE        pbBuff;
  431.     WORD        wType, wNumSect;
  432.  
  433.  
  434.     phandle = hStream;
  435.     memset(lpBuffer, 0, sizeof(PSRREADBUFF) - PSR_FRAMEBUFFER);
  436.     pbBuff    = lpBuffer->abData;
  437.     wType    = 0;
  438.     wNumSect= 0;
  439.  
  440.             // 退避バッファの内容を設定 ----------------------------
  441.     if(phandle->psector) {
  442.         psector = phandle->psector;
  443.         phandle->psector = NULL;
  444.         if(psector->abHead[2] == 'N') {
  445.             iPos    = 0x168;
  446.             wType    = PSR_STRTYPE_AUDIO;
  447.         } else if(psector->abHead[2] == 'J') {
  448.             iPos    = 0;
  449.             wType    = PSR_STRTYPE_MOVIE;
  450.             lpBuffer->nFrameNo    = psector->usFrameNo + 1;
  451.             lpBuffer->szFrame.cx    = 0x140;
  452.             lpBuffer->szFrame.cy    = 0x0e0;
  453.         } else {
  454.             // ####
  455.         }
  456.         iSize    = sizeof(psector->abData) - iPos;
  457.         memcpy(pbBuff, &psector->abData[iPos], iSize);
  458.         CdUnlockReadBuffer(phandle->hCdrom, psector);
  459.         pbBuff += iSize;
  460.         lpBuffer->nLength += iSize;
  461.         wNumSect = 1;
  462.     }
  463.  
  464.     while(1) {    // CDから読み込んで設定 --------------------------------
  465.         if(!(psector = CdReadSector(phandle->hCdrom, NULL)))    break;
  466.  
  467.                 // 音声データ - - - - - - - - - - - - - - - - -
  468.         if(psector->abHead[2] == 'N' || psector->abHead[2] == 'R') {
  469.             if(wType & PSR_STRTYPE_MOVIE) {
  470.                 phandle->psector = psector;
  471.                 break;
  472.             }
  473.             iPos    = 0x168;
  474.             wType    = PSR_STRTYPE_AUDIO;
  475.         }
  476.  
  477.                 // 映像データ - - - - - - - - - - - - - - - - -
  478.         else if(psector->abHead[2] == 'J') {
  479.             if(wType & PSR_STRTYPE_AUDIO) {
  480.                 phandle->psector = psector;
  481.                 break;
  482.             }
  483.             iPos    = 0;
  484.             wType    = PSR_STRTYPE_MOVIE;
  485.             lpBuffer->nFrameNo    = psector->usFrameNo + 1;
  486.             lpBuffer->szFrame.cx    = 0x140;
  487.             lpBuffer->szFrame.cy    = 0x0e0;
  488.         } else {
  489.             // ####
  490.         }
  491.         iSize    = sizeof(psector->abData) - iPos;
  492.         memcpy(pbBuff, &psector->abData[iPos], iSize);
  493.         CdUnlockReadBuffer(phandle->hCdrom, psector);
  494.         pbBuff += iSize;
  495.         lpBuffer->nLength += iSize;
  496.         wNumSect ++;
  497.         if(wNumSect >= phandle->wSectPerFrame)    break;
  498.     }
  499.  
  500.     return (lpBuffer->nLength ? TRUE : FALSE);
  501. }
  502.  
  503. /******************************************************************************/
  504. /*                                          */
  505. /*    PsrSeek() : 読み取り位置の設定                          */
  506. /*                                          */
  507. /******************************************************************************/
  508.  
  509. CEXPORT BOOL    PsrSeek(
  510.     HANDLE        hStream,    // ストリームハンドル
  511.     DWORD        dwPosition)    // 読み取り位置        1/1000秒単位
  512. {
  513.     _PTHANDLE    phandle;
  514.     LONG        lSector;
  515.  
  516.  
  517.     phandle = hStream;
  518.     lSector    = ((dwPosition * 15) / 1000) * (LONG)phandle->wSectPerFrame;
  519.  
  520.     if(phandle->psector) {
  521.         CdUnlockReadBuffer(phandle->hCdrom, phandle->psector);
  522.         phandle->psector    = NULL;
  523.     }
  524.     if(CdSetReadPointer(phandle->hCdrom, lSector, FILE_BEGIN) == 0xffffffff) {
  525.         return FALSE;
  526.     }
  527.  
  528.     PsrDecodeAudio(NULL, NULL, 0);
  529.     return TRUE;
  530. }
  531.  
  532. /******************************************************************************/
  533. /*                                          */
  534. /*    PsrDecodeAudio() : 音声データのデコード                      */
  535. /*                                          */
  536. /******************************************************************************/
  537.  
  538. CEXPORT DWORD    PsrDecodeAudio(
  539.     LPPSRREADBUFF    lpAudio,    // 音声データ
  540.     PVOID        pvBuffer,    // デコード後の音声データ
  541.     DWORD        nLength)    // lpBufferのバイト数
  542. {
  543.     static LONG    alPRE_L[2], alPRE_R[2];
  544.     DWORD        nSize;
  545.     INT        i, j, k, iTmp;
  546.     INT        iScaleL, iScaleR, iIndexL, iIndexR;
  547.     INT        aiFilterL[2], aiFilterR[2];
  548.     INT        aiValL[2], aiValR[2];
  549.     _PWAVEELM    pwave;
  550.     PBYTE        pbLeft, pbRight;
  551.  
  552.  
  553.     if(!lpAudio) {
  554.         alPRE_L[0] = alPRE_L[1] = 0;
  555.         alPRE_R[0] = alPRE_R[1] = 0;
  556.         return 0;
  557.     }
  558.     pwave    = pvBuffer;
  559.     nSize    = sizeof(_WAVEELM) * 0x69 * 14 * 2;
  560.     if(nLength < nSize)    return nSize;
  561.  
  562.     pbLeft    = lpAudio->abData;
  563.     pbRight    = lpAudio->abData + 0x690;
  564.  
  565.     for(i=0; i<0x69; i++) {
  566.         iScaleL    = 0x0c - (pbLeft[0] & 0x0f);
  567.         iIndexL    = (pbLeft[0] >> 4);
  568.         aiFilterL[0] = aiFILTER0[iIndexL];
  569.         aiFilterL[1] = aiFILTER1[iIndexL];
  570.  
  571.         iScaleR    = 0x0c - (pbRight[0] & 0x0f);
  572.         iIndexR    = (pbRight[0] >> 4);
  573.         aiFilterR[0] = aiFILTER0[iIndexR];
  574.         aiFilterR[1] = aiFILTER1[iIndexR];
  575.  
  576.         pbLeft    += 2;
  577.         pbRight    += 2;
  578.  
  579.         for(j=0; j<14; j++, pbLeft++, pbRight++) {
  580.             aiValL[0] = (pbLeft[0] & 0x0f);
  581.             aiValL[1] = (pbLeft[0] >> 4);
  582.             aiValR[0] = (pbRight[0] & 0x0f);
  583.             aiValR[1] = (pbRight[0] >> 4);
  584.             for(k=0; k<2; k++, pwave++) {
  585.                 if(aiValL[k] >= 8)    aiValL[k] -= 16;
  586.                 iTmp = (aiValL[k] << iScaleL);
  587.                 iTmp += ((alPRE_L[0] * aiFilterL[0] +
  588.                       alPRE_L[1] * aiFilterL[1]) >> 8);
  589.                 alPRE_L[1] = alPRE_L[0];
  590.                 alPRE_L[0] = _ROUND(iTmp);
  591.                 pwave[0].sLeft = (SHORT)alPRE_L[0];
  592.  
  593.                 if(aiValR[k] >= 8)    aiValR[k] -= 16;
  594.                 iTmp = (aiValR[k] << iScaleR);
  595.                 iTmp += ((alPRE_R[0] * aiFilterR[0] +
  596.                       alPRE_R[1] * aiFilterR[1]) >> 8);
  597.                 alPRE_R[1] = alPRE_R[0];
  598.                 alPRE_R[0] = _ROUND(iTmp);
  599.                 pwave[0].sRight = (SHORT)alPRE_R[0];
  600.             }
  601.         }
  602.     }
  603.     return nSize;
  604. }
  605.