?? malib.c
字號:
/****************************************************************************
*
* Copyright (C) 2002-2003 YAMAHA CORPORATION. All rights reserved.
*
* Module : malib.c
*
* Description : Libraly Functions
*
* Version : 2.0.0 2003.05.14
*
****************************************************************************/
#include "madefs.h"
#include "madebug.h"
#include "mamachdep.h"
#include "mammfcnv.h"
#include "malib.h"
/****************************************************************************
* macro
****************************************************************************/
#define MALIB_MAKEDWORD(a, b, c, d) (UINT32)(((UINT32)(a) << 24) | \
((UINT32)(b) << 16) | ((UINT32)(c) << 8) | (UINT32)(d))
/****************************************************************************
* define
****************************************************************************/
#define MALIB_SIZE_OF_CHUNKHEADER (8)
#define MALIB_SIZE_OF_CRC (2)
#define MALIB_SIZE_OF_MIN_CNTI (5)
/* for Phrase */
#define MALIB_CNTI_CLASS_YAMAHA (0x00)
#define MALIB_CNTI_TYPE_PHRASE (0xF0)
#define MALIB_PHRASE_TIMEBASE (20)
/* for Audio */
#define MALIB_MIN_STREAM_FS (4000)
#define MALIB_MAX_4BIT_MONO_FS (24000)
#define MALIB_MAX_4BIT_STEREO_FS (24000)
#define MALIB_MAX_8BIT_MONO_FS (12000)
#define MALIB_MAX_8BIT_STEREO_FS (12000)
#define MALIB_AUDIO_SIZE_MAX (0x100000) /* 1MByte */
/* Chunk ID */
#define MALIB_CHUNKID_MMMD 0x4D4D4D44
#define MALIB_CHUNKID_CNTI 0x434E5449
#define MALIB_CHUNKID_OPDA 0x4F504441
#define MALIB_CHUNKID_DCH 0x44636800
#define MALIB_CHUNKID_M5P 0x50726F00
#define MALIB_CHUNKID_MTR 0x4D545200
#define MALIB_CHUNKID_MSPI 0x4D737049
#define MALIB_CHUNKID_MTSU 0x4D747375
#define MALIB_CHUNKID_MTSQ 0x4D747371
#define MALIB_CHUNKID_MTSP 0x4D747370
#define MALIB_CHUNKID_MWA 0x4D776100
#define MALIB_CHUNKID_ATR 0x41545200
#define MALIB_CHUNKID_ASPI 0x41737049
#define MALIB_CHUNKID_ATSU 0x41747375
#define MALIB_CHUNKID_ATSQ 0x41747371
#define MALIB_CHUNKID_AWA 0x41776100
#define MALIB_CHUNKID_MTHV 0x4D746876
#define MALIB_CHUNKID_MHVS 0x4D687673
#define MALIB_CHUNKID_HVP 0x48565000
#define MALIB_CHUNKID_MHSC 0x4D687363
/****************************************************************************
* table
****************************************************************************/
static const UINT16 crctable[256] = {
0x0000U,0x1021U,0x2042U,0x3063U,0x4084U,0x50A5U,0x60C6U,0x70E7U,
0x8108U,0x9129U,0xA14AU,0xB16BU,0xC18CU,0xD1ADU,0xE1CEU,0xF1EFU,
0x1231U,0x0210U,0x3273U,0x2252U,0x52B5U,0x4294U,0x72F7U,0x62D6U,
0x9339U,0x8318U,0xB37BU,0xA35AU,0xD3BDU,0xC39CU,0xF3FFU,0xE3DEU,
0x2462U,0x3443U,0x0420U,0x1401U,0x64E6U,0x74C7U,0x44A4U,0x5485U,
0xA56AU,0xB54BU,0x8528U,0x9509U,0xE5EEU,0xF5CFU,0xC5ACU,0xD58DU,
0x3653U,0x2672U,0x1611U,0x0630U,0x76D7U,0x66F6U,0x5695U,0x46B4U,
0xB75BU,0xA77AU,0x9719U,0x8738U,0xF7DFU,0xE7FEU,0xD79DU,0xC7BCU,
0x48C4U,0x58E5U,0x6886U,0x78A7U,0x0840U,0x1861U,0x2802U,0x3823U,
0xC9CCU,0xD9EDU,0xE98EU,0xF9AFU,0x8948U,0x9969U,0xA90AU,0xB92BU,
0x5AF5U,0x4AD4U,0x7AB7U,0x6A96U,0x1A71U,0x0A50U,0x3A33U,0x2A12U,
0xDBFDU,0xCBDCU,0xFBBFU,0xEB9EU,0x9B79U,0x8B58U,0xBB3BU,0xAB1AU,
0x6CA6U,0x7C87U,0x4CE4U,0x5CC5U,0x2C22U,0x3C03U,0x0C60U,0x1C41U,
0xEDAEU,0xFD8FU,0xCDECU,0xDDCDU,0xAD2AU,0xBD0BU,0x8D68U,0x9D49U,
0x7E97U,0x6EB6U,0x5ED5U,0x4EF4U,0x3E13U,0x2E32U,0x1E51U,0x0E70U,
0xFF9FU,0xEFBEU,0xDFDDU,0xCFFCU,0xBF1BU,0xAF3AU,0x9F59U,0x8F78U,
0x9188U,0x81A9U,0xB1CAU,0xA1EBU,0xD10CU,0xC12DU,0xF14EU,0xE16FU,
0x1080U,0x00A1U,0x30C2U,0x20E3U,0x5004U,0x4025U,0x7046U,0x6067U,
0x83B9U,0x9398U,0xA3FBU,0xB3DAU,0xC33DU,0xD31CU,0xE37FU,0xF35EU,
0x02B1U,0x1290U,0x22F3U,0x32D2U,0x4235U,0x5214U,0x6277U,0x7256U,
0xB5EAU,0xA5CBU,0x95A8U,0x8589U,0xF56EU,0xE54FU,0xD52CU,0xC50DU,
0x34E2U,0x24C3U,0x14A0U,0x0481U,0x7466U,0x6447U,0x5424U,0x4405U,
0xA7DBU,0xB7FAU,0x8799U,0x97B8U,0xE75FU,0xF77EU,0xC71DU,0xD73CU,
0x26D3U,0x36F2U,0x0691U,0x16B0U,0x6657U,0x7676U,0x4615U,0x5634U,
0xD94CU,0xC96DU,0xF90EU,0xE92FU,0x99C8U,0x89E9U,0xB98AU,0xA9ABU,
0x5844U,0x4865U,0x7806U,0x6827U,0x18C0U,0x08E1U,0x3882U,0x28A3U,
0xCB7DU,0xDB5CU,0xEB3FU,0xFB1EU,0x8BF9U,0x9BD8U,0xABBBU,0xBB9AU,
0x4A75U,0x5A54U,0x6A37U,0x7A16U,0x0AF1U,0x1AD0U,0x2AB3U,0x3A92U,
0xFD2EU,0xED0FU,0xDD6CU,0xCD4DU,0xBDAAU,0xAD8BU,0x9DE8U,0x8DC9U,
0x7C26U,0x6C07U,0x5C64U,0x4C45U,0x3CA2U,0x2C83U,0x1CE0U,0x0CC1U,
0xEF1FU,0xFF3EU,0xCF5DU,0xDF7CU,0xAF9BU,0xBFBAU,0x8FD9U,0x9FF8U,
0x6E17U,0x7E36U,0x4E55U,0x5E74U,0x2E93U,0x3EB2U,0x0ED1U,0x1EF0U
};
static const UINT8 abMask[8] = {
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
/*******************************************************************************
* malib_MakeCRC
*
* Function:
* calculate CRC
* Argument:
* dSize size of data
* pbData pointer to data
* Return:
* value of CRC
*
*******************************************************************************/
UINT16 malib_MakeCRC(
UINT32 dSize,
UINT8* pbData
)
{
UINT16 wRes;
UINT8 bData;
wRes = 0xFFFFU;
while( --dSize >= 2 ){
bData = *pbData++;
wRes = (UINT16)((wRes << 8) ^ crctable[(UINT8)(wRes >> 8) ^ bData]);
}
return (UINT16)(~wRes & 0xFFFFU);
}
/*******************************************************************************
* malib_Decode_7bitData
*
* Function:
* change 7bit decode data to 8bit data
* Argument:
* pb7bit pointer to 7bit data
* d7Size size of 7bit data
* pb8bit pointer to 8bit data
* d8Size area size of 8bit data
* Return:
*
*
*******************************************************************/
UINT32 malib_Decode_7bitData(
UINT8* pb7bit,
UINT32 d7Size,
UINT8* pb8bit,
UINT32 d8Size
)
{
UINT32 dIndex7, dIndex8, dRemain, i;
UINT8 bMsb;
if((pb7bit == 0) || (d7Size == 0) || (pb8bit == 0) || (d8Size == 0))
return 0;
for (i = 0; i < d8Size; i ++)
pb8bit[i] = 0;
dIndex7 = 0;
dIndex8 = 0;
while (d7Size > dIndex7) {
if (d7Size >= dIndex7 + 8)
dRemain = 8;
else
dRemain = d7Size - dIndex7;
bMsb = pb7bit[dIndex7];
for (i = 1; i < dRemain; i++) {
if (d8Size <= dIndex8)
return dIndex8;
if (bMsb & abMask[i])
pb8bit[dIndex8] = (UINT8)(pb7bit[dIndex7 + i] | 0x80);
else
pb8bit[dIndex8] = (UINT8)(pb7bit[dIndex7 + i] & 0x7F);
dIndex8++;
}
dIndex7 += dRemain;
}
return dIndex8;
}
/****************************************************************************
* PhrChk_VoiceChunkCheck
*
* Function:
* Check SMAF/Phrase voice chunk body.
* Argument:
* pbVoc Pointer to the head of VOIC
* dSize size of VOIC chunk
* Return:
* 0 success.
* < 0 error code.
*
****************************************************************************/
static SINT32 PhrChk_VoiceChunkCheck(UINT8* pbVoc, UINT32 dSize)
{
UINT32 dChunkId;
UINT32 dChunkSize;
while(dSize >= (UINT32)(MALIB_SIZE_OF_CHUNKHEADER)) {
dChunkId = MALIB_MAKEDWORD(pbVoc[0], pbVoc[1], pbVoc[2], pbVoc[3]);
dChunkSize = MALIB_MAKEDWORD(pbVoc[4], pbVoc[5], pbVoc[6], pbVoc[7]);
pbVoc += (UINT32)MALIB_SIZE_OF_CHUNKHEADER;
/* Check chunk size */
if(dSize < (UINT32)(MALIB_SIZE_OF_CHUNKHEADER + dChunkSize)) {
return (MASMW_ERROR_CHUNK_SIZE);
}
/* Update */
pbVoc += dChunkSize;
dSize -= (UINT32)(MALIB_SIZE_OF_CHUNKHEADER + dChunkSize);
}
return (MASMW_SUCCESS);
}
/****************************************************************************
* PhrChk_SequenceChunkCheck
*
* Function:
* Check SMAF/Phrase sequence chunk.
* Argument:
* pbSeq Pointer to the head of SEQU
* dSize size of SEQU chunk
* Return:
* >=0 playback time[tick].
* < 0 error code.
*
****************************************************************************/
static SINT32 PhrChk_SequenceChunkCheck(UINT8* pbSeq, UINT32 dSize)
{
UINT32 dData;
UINT32 dIdx;
UINT32 dDuration;
UINT32 dPlayTime;
/* Get play back time */
dIdx = 0L;
dPlayTime = 0L;
while(dIdx < dSize) {
/* Check Size */
if(dSize < (dIdx + 2L)) return (MASMW_ERROR_CHUNK_SIZE);
/* Duration 1 or 2byte */
dDuration = (UINT32)(pbSeq[dIdx++]);
if(dDuration & 0x80) {
dDuration = (UINT32)((((dDuration & 0x7F) << 7)
+ (UINT32)pbSeq[dIdx++]) + 128);
}
/* Update play back time */
dPlayTime += dDuration;
/* Event */
if(dSize < (dIdx + 2L)) return (MASMW_ERROR_CHUNK_SIZE);
dData = (UINT32)pbSeq[dIdx++];
switch (dData) {
case 0x00L:
/* Control Message */
dData = (UINT32)pbSeq[dIdx++];
if((dData & 0x30) == 0x30L) { /* 3byte */
if(dSize < (dIdx + 1L)) {
return (MASMW_ERROR_CHUNK_SIZE);
}
dIdx++;
}
break;
case 0xFFL:
/* Exclusive Message or NOP */
dData = (UINT32)pbSeq[dIdx++];
if(dData == 0xF0L) {
if(dSize < (dIdx + 1L)) {
return (MASMW_ERROR_CHUNK_SIZE);
}
dData = (UINT32)pbSeq[dIdx++];
if(dSize < (UINT32)(dIdx + dData)) {
return (MASMW_ERROR_CHUNK_SIZE);
}
dIdx += dData;
}
break;
default:
/* Note Message */
/* Gatetime 1 or 2byte */
dDuration = (UINT32)pbSeq[dIdx++];
if(dDuration & 0x80) {
if(dSize < (dIdx + 1L)) {
return (MASMW_ERROR_CHUNK_SIZE);
}
dDuration = (UINT32)(((dDuration & 0x7F) << 7)
+ (UINT32)pbSeq[dIdx++] + 128);
}
break;
}
}
if(dPlayTime <= 1) { /* 20ms */
return (MASMW_ERROR_SHORT_LENGTH);
}
return (SINT32)(dPlayTime);
}
/****************************************************************************
* PhrChk_PhraseBody
*
* Function:
* Check SMAF/Phrase chunk.
* Argument:
* pbData Pointer to the head of MMMG
* dSize size of MMMG chunk
* pPi pointer to MALIBPHRINFO
* Return:
* 0 success.
* < 0 error code.
*
****************************************************************************/
static SINT32 PhrChk_PhraseBody(UINT8* pbData, UINT32 dSize,
PMALIBPHRINFO pPi)
{
SINT32 sdRet;
UINT32 dFound;
UINT32 dChunkId;
UINT32 dChunkSize;
if(dSize < 2) return (MASMW_ERROR_CHUNK_SIZE);
/* Check Version */
pPi->dVersion = (UINT32)(*pbData);
if((pPi->dVersion != 1L) && (pPi->dVersion != 2L)) {
return (MASMW_ERROR_FILE);
}
if(pPi->dErrChk) {
/* Check Timer base */
if(*(pbData + 1) != MALIB_PHRASE_TIMEBASE) {
return (MASMW_ERROR_FILE);
}
}
/* Search "VOIC", "SEQU" Chunk */
dFound = 0x00L;
pbData += 2; /* Skip */
dSize -= 2L;
while(dSize >= (UINT32)MALIB_SIZE_OF_CHUNKHEADER) {
dChunkId = MALIB_MAKEDWORD(pbData[0], pbData[1], pbData[2], pbData[3]);
dChunkSize = MALIB_MAKEDWORD(pbData[4], pbData[5], pbData[6], pbData[7]);
pbData += (UINT32)MALIB_SIZE_OF_CHUNKHEADER;
/* Check chunk size */
if(dSize < (UINT32)(MALIB_SIZE_OF_CHUNKHEADER + dChunkSize)) {
return (MASMW_ERROR_CHUNK_SIZE);
}
if( (dChunkId == MALIB_MAKEDWORD('V', 'O', 'I', 'C')) &&
!(dFound & 0x01)) {
sdRet = PhrChk_VoiceChunkCheck(pbData, dChunkSize);
if(sdRet < MASMW_SUCCESS) return (sdRet);
pPi->pbVoice = pbData;
pPi->dVoiceSize = dChunkSize;
dFound |= 0x01L;
}
else if((dChunkId == MALIB_MAKEDWORD('S', 'E', 'Q', 'U')) &&
!(dFound & 0x02)) {
sdRet = PhrChk_SequenceChunkCheck(pbData, dChunkSize);
if(sdRet < MASMW_SUCCESS) return (sdRet);
pPi->pbSeq = pbData;
pPi->dSeqSize = dChunkSize;
pPi->dPlayTime = (UINT32)sdRet;
dFound |= 0x02L;
}
/* Update */
pbData += dChunkSize;
dSize -= (UINT32)(dChunkSize + MALIB_SIZE_OF_CHUNKHEADER);
}
if((dFound & 0x02) == 0x00L) {
return (MASMW_ERROR_CHUNK);
}
return (MASMW_SUCCESS);
}
/****************************************************************************
* SmafPhrChecker
*
* Function:
* Check SMAF/Phrase data.
* Argument:
* pbData Pointer to SMAF/Phrase data
* dSize size of data
* pPi pointer to MALIBPHRINFO
* Return:
* 0 success.
* < 0 error code.
*
****************************************************************************/
static SINT32 SmafPhrChecker(UINT8* pbData, UINT32 dSize, PMALIBPHRINFO pPi)
{
UINT32 dCRC;
UINT32 dRemain;
UINT32 dChunkId;
UINT32 dChunkSize;
if(dSize < (UINT32)(MALIB_SIZE_OF_CHUNKHEADER + MALIB_SIZE_OF_CRC))
return (MASMW_ERROR_CHUNK_SIZE);
/* Check header ID and size */
dChunkId = MALIB_MAKEDWORD(pbData[0], pbData[1], pbData[2], pbData[3]);
dChunkSize = MALIB_MAKEDWORD(pbData[4], pbData[5], pbData[6], pbData[7]);
if(dChunkId != MALIB_MAKEDWORD('M', 'M', 'M', 'D')) {
return (MASMW_ERROR_CHUNK);
}
if((UINT32)(dChunkSize + MALIB_SIZE_OF_CHUNKHEADER) != dSize) {
return (MASMW_ERROR_CHUNK_SIZE);
}
/* Check CRC */
if(pPi->dErrChk) {
dCRC = (UINT32)(((UINT32)pbData[dSize - 2L] << 8) | \
((UINT32)pbData[dSize - 1L] << 0));
if((UINT32)malib_MakeCRC(dSize, pbData) != dCRC) {
return (MASMW_ERROR_FILE);
}
}
pbData += (UINT32)MALIB_SIZE_OF_CHUNKHEADER;
dRemain = dChunkSize;
if(dRemain < (UINT32)(MALIB_SIZE_OF_CHUNKHEADER
+ MALIB_SIZE_OF_MIN_CNTI + MALIB_SIZE_OF_CRC)) {
return (MASMW_ERROR_FILE);
}
/* Check Contents Info ID */
dChunkId = MALIB_MAKEDWORD(pbData[0], pbData[1], pbData[2], pbData[3]);
dChunkSize = MALIB_MAKEDWORD(pbData[4], pbData[5], pbData[6], pbData[7]);
pbData += MALIB_SIZE_OF_CHUNKHEADER;
if(dChunkId != MALIB_MAKEDWORD('C', 'N', 'T', 'I')) {
return (MASMW_ERROR_CHUNK);
}
if( (dChunkSize < (UINT32)MALIB_SIZE_OF_MIN_CNTI) ||
(dRemain < (UINT32)(MALIB_SIZE_OF_CHUNKHEADER
+ dChunkSize + MALIB_SIZE_OF_CRC))) {
return (MASMW_ERROR_CHUNK_SIZE);
}
/* Check contents class & type */
if(pPi->dErrChk) {
if(*(pbData) != MALIB_CNTI_CLASS_YAMAHA) {
return (MASMW_ERROR_CONTENTS_CLASS);
}
if(*(pbData + 1) != MALIB_CNTI_TYPE_PHRASE) {
return (MASMW_ERROR_CONTENTS_TYPE);
}
}
pbData += dChunkSize;
dRemain -= (UINT32)(dChunkSize + MALIB_SIZE_OF_CHUNKHEADER);
/* Phrase Check */
while(dRemain >= (UINT32)(MALIB_SIZE_OF_CHUNKHEADER + MALIB_SIZE_OF_CRC)) {
/* Search "MMMG" Chunk */
dChunkId = MALIB_MAKEDWORD(pbData[0], pbData[1], pbData[2], pbData[3]);
dChunkSize = MALIB_MAKEDWORD(pbData[4], pbData[5], pbData[6], pbData[7]);
pbData += (UINT32)MALIB_SIZE_OF_CHUNKHEADER;
if(dRemain < (UINT32)(MALIB_SIZE_OF_CHUNKHEADER
+ dChunkSize + MALIB_SIZE_OF_CRC)) {
return (MASMW_ERROR_CHUNK_SIZE);
}
if(dChunkId == MALIB_MAKEDWORD('M', 'M', 'M', 'G')) {
/* Support only the first "MMMG" Chunk */
return (PhrChk_PhraseBody(pbData, dChunkSize, pPi));
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -