/*--------------------------------------------------------------------------* Project: Revolution Audio sound file converter File: output.c Copyright (C)1998-2006 Nintendo All Rights Reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Log: output.c,v $ Revision 1.2 02/09/2006 06:26:26 aka Changed copyright. *--------------------------------------------------------------------------*/ #include #include #include #include "soundconv.h" #include "endian.h" #include "types.h" /*--------------------------------------------------------------------------* exports for dsptool.dll *--------------------------------------------------------------------------*/ typedef int (*FUNCTION3)(int); extern FUNCTION3 getNibbleAddress; /*--------------------------------------------------------------------------* local variables *--------------------------------------------------------------------------*/ u32 soundEntries; u32 soundAdpcmEntries; u32 soundByteOffset; SNDCONVDATA soundConvdata[0xFFFF]; ADPCMINFO soundAdpcminfo[0xFFFF]; FILE *outputHeader; FILE *outputTable; FILE *outputSamples; /*--------------------------------------------------------------------------* add an entry *--------------------------------------------------------------------------*/ void soundOutputAddEntry( u32 format, u32 dataBytes, void *buffer, u32 samples, u32 sampleRate, u32 loopStart, u32 loopEnd, ADPCMINFO *adpcminfo, char *headerId ) { SNDCONVDATA *sndconvdata = &soundConvdata[soundEntries]; switch (format) { case SOUND_FORMAT_ADPCM: // 8 byte-aligned ADPCM buffers while (soundByteOffset % 8) { char ch = 0; fwrite(&ch, 1, 1, outputSamples); soundByteOffset++; } // looped sound if (loopEnd) { sndconvdata->type = SP_TYPE_ADPCM_LOOPED; sndconvdata->sampleRate = sampleRate; sndconvdata->loopAddr = (soundByteOffset << 1) + getNibbleAddress(loopStart); sndconvdata->loopEndAddr = (soundByteOffset << 1) + getNibbleAddress(loopEnd); sndconvdata->endAddr = (soundByteOffset << 1) + getNibbleAddress(samples - 1); sndconvdata->currentAddr = (soundByteOffset << 1) + getNibbleAddress(0); sndconvdata->adpcm = 0; } else { sndconvdata->type = SP_TYPE_ADPCM_ONESHOT; sndconvdata->sampleRate = sampleRate; sndconvdata->loopAddr = 0; sndconvdata->loopEndAddr = 0; sndconvdata->endAddr = (soundByteOffset << 1) + getNibbleAddress(samples - 1); sndconvdata->currentAddr = (soundByteOffset << 1) + getNibbleAddress(0); sndconvdata->adpcm = 0; } // write the buffer to data file fwrite(buffer, 1, dataBytes, outputSamples); soundByteOffset += dataBytes; // store the ADPCMINFO memcpy( &soundAdpcminfo[soundAdpcmEntries], adpcminfo, sizeof(ADPCMINFO) ); soundAdpcmEntries++; break; case SOUND_FORMAT_PCM8: // looped sound if (loopEnd) { sndconvdata->type = SP_TYPE_PCM8_LOOPED; sndconvdata->sampleRate = sampleRate; sndconvdata->loopAddr = soundByteOffset + loopStart; sndconvdata->loopEndAddr = soundByteOffset + loopEnd; sndconvdata->endAddr = soundByteOffset + samples - 1; sndconvdata->currentAddr = soundByteOffset; sndconvdata->adpcm = 0; } else { sndconvdata->type = SP_TYPE_PCM8_ONESHOT; sndconvdata->sampleRate = sampleRate; sndconvdata->loopAddr = 0; sndconvdata->loopEndAddr = 0; sndconvdata->endAddr = soundByteOffset + samples - 1; sndconvdata->currentAddr = soundByteOffset; sndconvdata->adpcm = 0; } // write the buffer to data file fwrite(buffer, 1, dataBytes, outputSamples); soundByteOffset += dataBytes; break; case SOUND_FORMAT_PCM16: // 16 bit-aligned the data if (soundByteOffset & 1) { char ch = 0; fwrite(&ch, 1, 1, outputSamples); soundByteOffset++; } // looped sound if (loopEnd) { sndconvdata->type = SP_TYPE_PCM16_LOOPED; sndconvdata->sampleRate = sampleRate; sndconvdata->loopAddr = (soundByteOffset >> 1) + loopStart; sndconvdata->loopEndAddr = (soundByteOffset >> 1) + loopEnd; sndconvdata->endAddr = (soundByteOffset >> 1) + samples - 1; sndconvdata->currentAddr = soundByteOffset >> 1; sndconvdata->adpcm = 0; } else { sndconvdata->type = SP_TYPE_PCM16_ONESHOT; sndconvdata->sampleRate = sampleRate; sndconvdata->loopAddr = 0; sndconvdata->loopEndAddr = 0; sndconvdata->endAddr = (soundByteOffset >> 1) + samples - 1; sndconvdata->currentAddr = soundByteOffset >> 1; sndconvdata->adpcm = 0; } // reverse the endian then write the buffer to data file reverse_buffer_16(buffer, samples); fwrite(buffer, 1, dataBytes, outputSamples); soundByteOffset += dataBytes; break; } if (outputHeader) fprintf(outputHeader, "#define %s\t\t%d\n", headerId, soundEntries); soundEntries++; } /*--------------------------------------------------------------------------* print the table file ... call this once at end of program *--------------------------------------------------------------------------*/ void soundOutputWriteTable(void) { if (outputTable) { u32 data; SNDCONVDATA *sndconvdata; ADPCMINFO *adpcminfo; // write number of entries data = reverse_endian_32(soundEntries); fwrite(&data, 1, sizeof(u32), outputTable); // write sound entries sndconvdata = soundConvdata; while (soundEntries) { sndconvdata->type = reverse_endian_32(sndconvdata->type); sndconvdata->sampleRate = reverse_endian_32(sndconvdata->sampleRate); sndconvdata->loopAddr = reverse_endian_32(sndconvdata->loopAddr); sndconvdata->loopEndAddr = reverse_endian_32(sndconvdata->loopEndAddr); sndconvdata->endAddr = reverse_endian_32(sndconvdata->endAddr); sndconvdata->currentAddr = reverse_endian_32(sndconvdata->currentAddr); sndconvdata->adpcm = 0; fwrite(sndconvdata, 1, sizeof(SNDCONVDATA), outputTable); sndconvdata++; soundEntries--; } // write apdcm entries adpcminfo = soundAdpcminfo; while (soundAdpcmEntries) { u16 *p; int i; p = (u16*)adpcminfo; for (i = 0; i < sizeof(ADPCMINFO) / 2; i++) { *p = reverse_endian_16(*p); p++; } fwrite(adpcminfo, 1, sizeof(ADPCMINFO), outputTable); adpcminfo++; soundAdpcmEntries--; } } } /*--------------------------------------------------------------------------* print comment to header file *--------------------------------------------------------------------------*/ void soundOutputComment(char *ch) { if (outputHeader) fwrite(ch, strlen(ch), 1, outputHeader); } /*--------------------------------------------------------------------------* quit code module *--------------------------------------------------------------------------*/ void soundOutputQuit(void) { soundOutputWriteTable(); if (outputHeader) fclose(outputHeader); if (outputTable) fclose(outputTable); if (outputSamples) fclose(outputSamples); } /*--------------------------------------------------------------------------* init code module *--------------------------------------------------------------------------*/ int soundOutputInit(char *name) { char ch[1024]; soundEntries = 0; soundAdpcmEntries = 0; soundByteOffset = 0; sprintf(ch, "%s.h", name); outputHeader = fopen(ch, "w"); sprintf(ch, "%s.spt", name); outputTable = fopen(ch, "wb"); sprintf(ch, "%s.spd", name); outputSamples = fopen(ch, "wb"); if (outputHeader && outputTable && outputSamples) return STATUS_SUCCESS; soundOutputQuit(); if (outputHeader == NULL) { printf("Error: Can't open %s.h\n", name); } if (outputTable == NULL) { printf("Error: Can't open %s.spt\n", name); } if (outputSamples == NULL) { printf("Error: Can't open %s.spd\n", name); } return STATUS_ERROR; }