29 # define CHUNK_ID_MSP1 0x4d535031 30 # define CHUNK_ID_RLP1 0x524c5031 31 # define CHUNK_ID_SMP1 0x534d5031 32 # define CHUNK_ID_SMD1 0x534d4431 33 # define CHUNK_ID_NAME 0x4e414d45 34 #else // little endian 35 # define CHUNK_ID_MSP1 0x3150534d 36 # define CHUNK_ID_RLP1 0x31504c52 37 # define CHUNK_ID_SMP1 0x31504d53 38 # define CHUNK_ID_SMD1 0x31444d53 39 # define CHUNK_ID_NAME 0x454d414e 40 #endif // WORDS_BIGENDIAN 42 #define SMD1_CHUNK_HEADER_SZ 12 47 static const String PATH_SEP =
"\\";
49 static const String PATH_SEP =
"/";
55 template<
unsigned int SZ>
58 int n = (int) ck->
Read(buf, SZ, 1);
60 throw Exception(
"Premature end while reading text field");
67 return readText<24>(ck);
72 return readText<16>(ck);
77 return readText<12>(ck);
82 size_t pos = filename.find_last_of(
'.');
83 if (pos == String::npos)
return filename;
84 return filename.substr(0, pos);
90 KSFSample::KSFSample(
const String& filename) {
102 throw Exception(
"Not a Korg sample file ('SMP1' chunk not found)");
104 throw Exception(
"Not a Korg sample file ('SMP1' chunk size too small)");
115 throw Exception(
"Not a Korg sample file ('SMD1' chunk not found)");
117 throw Exception(
"Not a Korg sample file ('SMD1' chunk size too small)");
126 KSFSample::~KSFSample() {
127 if (RAMCache.
pStart)
delete[] (int8_t*) RAMCache.
pStart;
128 if (riff)
delete riff;
199 if (RAMCache.
pStart)
delete[] (int8_t*) RAMCache.
pStart;
200 unsigned long allocationsize = (SampleCount + NullSamplesCount) *
FrameSize();
202 RAMCache.
pStart =
new int8_t[allocationsize];
235 if (RAMCache.
pStart)
delete[] (int8_t*) RAMCache.
pStart;
253 unsigned long samplePos =
GetPos();
255 case RIFF::stream_curpos:
256 samplePos += SampleCount;
258 case RIFF::stream_end:
261 case RIFF::stream_backward:
262 samplePos -= SampleCount;
264 case RIFF::stream_start:
266 samplePos = SampleCount;
270 unsigned long bytes = samplePos *
FrameSize();
272 unsigned long result = smd1->
SetPos(SMD1_CHUNK_HEADER_SZ + bytes);
273 return (result - SMD1_CHUNK_HEADER_SZ) /
FrameSize();
303 unsigned long samplestoread = SampleCount, totalreadsamples = 0, readsamples;
305 if (samplestoread)
do {
307 samplestoread -= readsamples;
308 totalreadsamples += readsamples;
309 }
while (readsamples && samplestoread);
311 return totalreadsamples;
321 uint8_t KSFSample::CompressionID()
const {
325 bool KSFSample::IsCompressed()
const {
329 bool KSFSample::Use2ndStart()
const {
333 String KSFSample::FileName()
const {
334 return riff->GetFileName();
341 : parent(parent), rlp1(rlp1)
344 Transpose = (OriginalKey >> 7) & 1;
354 KMPRegion::~KMPRegion() {
357 String KMPRegion::FullSampleFileName()
const {
359 PATH_SEP + SampleFileName;
369 KMPInstrument::KMPInstrument(
const String& filename) {
377 throw Exception(
"Not a Korg instrument file ('MSP1' chunk not found)");
379 throw Exception(
"Not a Korg instrument file ('MSP1' chunk size too small)");
393 throw Exception(
"Not a Korg instrument file ('RLP1' chunk not found)");
394 if (rlp1->
GetSize() < 18 * nSamples)
395 throw Exception(
"Not a Korg instrument file ('RLP1' chunk size too small)");
396 for (
int i = 0; i < nSamples; ++i) {
398 regions.push_back(region);
402 KMPInstrument::~KMPInstrument() {
403 if (riff)
delete riff;
404 for (
int i = 0; i < regions.size(); ++i)
408 KMPRegion* KMPInstrument::GetRegion(
int index) {
409 if (index < 0 || index >= regions.size())
411 return regions[index];
414 int KMPInstrument::GetRegionCount()
const {
415 return (
int) regions.size();
418 bool KMPInstrument::Use2ndStart()
const {
427 return (!Name24.empty()) ? Name24 : Name16;
430 String KMPInstrument::FileName()
const {
431 return riff->GetFileName();
440 void Exception::PrintMessage() {
441 std::cout <<
"Korg::Exception: " << Message << std::endl;
unsigned long SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence=RIFF::stream_start)
Sets the position within the sample (in sample points, not in bytes).
stream_whence_t
File stream position dependent to these relations.
String readText16(RIFF::Chunk *ck)
Read 16 bytes of ASCII text from given chunk and return it as String.
String readText12(RIFF::Chunk *ck)
Read 12 bytes of ASCII text from given chunk and return it as String.
file_offset_t GetSize() const
Chunk size in bytes (without header, thus the chunk data body)
String removeFileTypeExtension(const String &filename)
For example passing "FOO.KMP" will return "FOO".
String Name() const
Returns the long name (Name24) if it was stored in the file, otherwise returns the short name (Name16...
file_offset_t Size
Size of the actual data in the buffer in bytes.
uint32_t SamplePoints
Currently the library expects all Korg samples to be Mono, thus the value here might be incorrect in ...
uint8_t Attributes
Bit field of flags, better call IsCompressed(), CompressionID() and Use2ndStart() instead of accessin...
String readText24(RIFF::Chunk *ck)
Read 24 bytes of ASCII text from given chunk and return it as String.
uint8_t Channels
Number of audio channels (seems to be always 1, thus Mono for all Korg sound files ATM)...
String Name
Sample name for drums (since this name is always stored with 16 bytes, this name must never be longer...
buffer_t LoadSampleDataWithNullSamplesExtension(uint NullSamplesCount)
Loads the whole sample wave into RAM.
file_offset_t Read(void *pData, file_offset_t WordCount, file_offset_t WordSize)
Reads WordCount number of data words with given WordSize and copies it into a buffer pointed by pData...
Pointer address and size of a buffer.
file_offset_t SetPos(file_offset_t Where, stream_whence_t Whence=stream_start)
Sets the position within the chunk body, thus within the data portion of the chunk (in bytes)...
unsigned long Read(void *pBuffer, unsigned long SampleCount)
Reads SampleCount number of sample points from the current position into the buffer pointed by pBuffe...
KORG sound format specific classes and definitions.
String libraryVersion()
Returns version of this C++ library.
void * pStart
Points to the beginning of the buffer.
file_offset_t ReadUint32(uint32_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 32 Bit unsigned integer words and copies it into the buffer pointed by pDat...
Chunk * GetSubChunk(uint32_t ChunkID)
Returns subchunk with chunk ID ChunkID within this chunk list.
unsigned long GetPos() const
Returns the current position in the sample (in sample points).
void ReleaseSampleData()
Frees the cached sample from RAM if loaded with LoadSampleData() previously.
Region of a .KMP multi sample file.
Not a "real" RIFF file: First chunk in file is an ordinary data chunk, not a List chunk...
file_offset_t ReadInt8(int8_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 8 Bit signed integer words and copies it into the buffer pointed by pData...
int FrameSize() const
Returns the size of one sample point of this sample in bytes.
file_offset_t NullExtensionSize
The buffer might be bigger than the actual data, if that's the case that unused space at the end of t...
String libraryName()
Returns the name of this C++ library.
uint32_t SampleRate
i.e. 44100
uint8_t BitDepth
i.e. 8 or 16
File * GetFile() const
Returns pointer to the chunk's File object.
Will be thrown whenever an error occurs while handling a RIFF file.
buffer_t LoadSampleData()
Loads the whole sample wave into RAM.
file_offset_t GetPos() const
Current read/write position within the chunk data body (starting with 0).
Korg format specific exception.
file_offset_t ReadUint8(uint8_t *pData, file_offset_t WordCount=1)
Reads WordCount number of 8 Bit unsigned integer words and copies it into the buffer pointed by pData...
buffer_t GetCache() const
Returns current cached sample points.