ref: b96d21bfc2516311ff6b5e6af3d6d0ae5ba0cae2
author: qwx <[email protected]>
date: Wed Oct 25 22:07:12 EDT 2023
import korg volca sample syro sdk retrieved from https://github.com/korginc/volcasample
--- /dev/null
+++ b/LICENSE
@@ -1,0 +1,19 @@
+Copyright © 2023 qwx
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null
+++ b/korg_syro_comp.c
@@ -1,0 +1,609 @@
+/************************************************************************
+ SYRO for volca sample
+ comprss PCM
+ ***********************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include "korg_syro_type.h"
+#include "korg_syro_volcasample.h"
+#include "korg_syro_func.h"
+#include "korg_syro_comp.h"
+
+typedef struct {
+ const uint8_t *ptr;
+ uint32_t NumOfSample;
+ int bitlen_eff;
+ Endian SampleEndian;
+ uint16_t sum;
+ uint16_t padding;
+} ReadSample;
+
+typedef struct {
+ uint8_t *ptr;
+ int BitCount;
+ int ByteCount;
+} WriteBit;
+
+
+/*-----------------------------------------------------------------------------
+ Write Bit
+ ** Update pwp member(ptr, BitCount, ByteCount)
+ -----------------------------------------------------------------------------*/
+static void SyroComp_WriteBit(WriteBit *pwp, uint32_t dat, int bit)
+{
+ //-- write bit as big-endian format.(MSB->LSB) --
+
+ dat <<= (32-bit);
+ dat >>= pwp->BitCount;
+
+ for (;;) {
+ if (pwp->BitCount) {
+ *pwp->ptr |= (uint8_t)(dat>>24);
+ } else {
+ *pwp->ptr = (uint8_t)(dat>>24);
+ }
+ if ((pwp->BitCount + bit) >= 8) {
+ bit -= (8 - pwp->BitCount);
+ pwp->BitCount=0;
+ pwp->ByteCount++;
+ pwp->ptr++;
+ dat <<= 8;
+ } else {
+ pwp->BitCount += bit;
+ bit = 0;
+ }
+ if (!bit) {
+ break;
+ }
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ Read PCM (fixed to 16bit)
+ -----------------------------------------------------------------------------*/
+static int32_t SyroComp_GetPcm(ReadSample *prp)
+{
+ int32_t dat;
+
+ if (prp->SampleEndian == LittleEndian) {
+ dat = (int32_t)((int8_t)(prp->ptr[1]));
+ dat <<= 8;
+ dat |= (int32_t)(*prp->ptr);
+ prp->ptr += 2;
+ } else {
+ dat = (int32_t)((int8_t)(*prp->ptr++));
+ dat <<= 8;
+ dat |= (int32_t)(*prp->ptr++);
+ }
+
+ /*----- convert, 16Bit -> specified bit ----*/
+ if (prp->bitlen_eff < 16) {
+ dat /= (1 << (16 - prp->bitlen_eff)); //replace from dat >>= (16 - prp->bitlen_eff);
+ prp->sum += (uint16_t)(dat << (16 - prp->bitlen_eff));
+ } else {
+ prp->sum += (uint16_t)dat;
+ }
+
+ return dat;
+}
+
+/*-----------------------------------------------------------------------------
+ Generate bit-map, store to map_buffer
+ -----------------------------------------------------------------------------*/
+static void SyroComp_MakeMapBuffer(uint8_t *map_buffer, ReadSample *prp, int *pBitBase, int nBitBase, int type)
+{
+ int i;
+ uint32_t mcnt;
+ int32_t dat[4];
+ int32_t datn;
+ int bnum;
+
+ memset(map_buffer, 0, VOLCASAMPLE_COMP_BLOCK_LEN);
+
+ bnum = 0;
+ mcnt = 0;
+ map_buffer[mcnt++] = (uint8_t)prp->bitlen_eff; /* fix to full-bit 1st~3rd */
+ map_buffer[mcnt++] = (uint8_t)prp->bitlen_eff;
+ map_buffer[mcnt++] = (uint8_t)prp->bitlen_eff;
+ if (mcnt >= prp->NumOfSample) {
+ return;
+ }
+
+ dat[3] = SyroComp_GetPcm(prp);
+ dat[2] = SyroComp_GetPcm(prp);
+ dat[1] = SyroComp_GetPcm(prp);
+ for (;;) {
+ dat[0] = SyroComp_GetPcm(prp);
+ datn = dat[0];
+ if (type) {
+ datn -= (dat[1]*2 - dat[2]);
+ }
+ if (datn < 0) {
+ datn = -datn;
+ }
+
+ for (i=0; i<nBitBase; i++) {
+ bnum = pBitBase[i];
+ if (datn < ( 1 << (bnum-1))) break;
+ }
+ if (i == nBitBase) {
+ bnum = prp->bitlen_eff;
+ }
+
+ map_buffer[mcnt++] = (uint8_t)bnum;
+ if (mcnt == prp->NumOfSample) {
+ break;
+ }
+ dat[3] = dat[2];
+ dat[2] = dat[1];
+ dat[1] = dat[0];
+ }
+}
+
+/*-----------------------------------------------------------------------------
+ convert bit-map in map_buffer.
+ for example, bit=4,4,1,4 -> bit 4,4,4,4
+ -----------------------------------------------------------------------------*/
+static void SyroComp_MakeMap_BitConv(uint8_t *map_buffer, int num_of_sample, int bitlen)
+{
+ int i, j;
+ int dat, dat1;
+ int datlo, dathi, datuse;
+ int st;
+ int pls, min;
+
+ for (i=0; i<bitlen; i++) {
+
+ st = -1;
+ for (j=0; j<(num_of_sample+1); j++) {
+ dat = (j<num_of_sample) ? map_buffer[j] : 0;
+ if (dat==i) {
+ if (st==-1) {
+ st=j;
+ }
+ } else {
+ if (st!=-1) {
+ dat1 = st ? map_buffer[st-1] : 0;
+ if (dat<dat1) {
+ datlo = dat;
+ dathi = dat1;
+ } else {
+ datlo = dat1;
+ dathi = dat;
+ }
+ if (dathi > i) {
+ datuse = dathi;
+ if (datlo > i) {
+ datuse = datlo;
+ }
+
+ pls = (datuse-i) * (j-st);
+ min = 2 + i;
+ if (datuse==bitlen) {
+ min++;
+ }
+ if (dathi==datlo) {
+ min += 2 + datlo;
+ if (datlo==bitlen) {
+ min++;
+ }
+ }
+ if (min>=pls) {
+ for (; st<j; st++) {
+ map_buffer[st] = (uint8_t)datuse;
+ }
+ }
+ }
+ st = -1;
+ }
+ }
+ }
+ }
+}
+/*-----------------------------------------------------------------------------
+ Get compressed size form map_buffer
+ -----------------------------------------------------------------------------*/
+static int SyroComp_GetCompSizeFromMap(uint8_t *map_buffer, ReadSample *prp, int type)
+{
+ int i, pr, bit, prbit;
+ int32_t dat, datlim;
+ int bitlen;
+ int32_t dath[4];
+
+ bitlen = prp->bitlen_eff;
+ datlim = -(1<<(bitlen-1));
+
+ dath[0] = 0;
+ dath[1] = 0;
+ dath[2] = 0;
+ dath[3] = 0;
+
+ prbit = map_buffer[0];
+ pr = 16 + 2; // 16=BitLen(4)*4, 2=1st Header
+
+ for (i=0; i<(int)prp->NumOfSample; i++) {
+ dath[0] = SyroComp_GetPcm(prp);
+ bit = map_buffer[i];
+ if (bit != prbit) {
+ pr += prbit;
+ if (prbit==bitlen) {
+ pr++;
+ }
+ pr += 2;
+ prbit = bit;
+ }
+ pr += bit;
+ if ((prbit < bitlen) && type) {
+ dat = dath[0] - (dath[1]*2 - dath[2]);
+ } else {
+ dat = dath[0];
+ }
+ if (bit==bitlen && dat==datlim) {
+ pr++;
+ }
+ dath[3] = dath[2];
+ dath[2] = dath[1];
+ dath[1] = dath[0];
+ }
+ pr += prbit;
+ if (prbit==bitlen) {
+ pr++;
+ }
+
+ return pr;
+}
+
+/*-----------------------------------------------------------------------------
+ Make map (single type)
+ (prp is updated)
+
+ memo : comppcm.c-MakeMap2
+ -----------------------------------------------------------------------------*/
+static int SyroComp_MakeMap_SingleType(uint8_t *map_buffer, ReadSample *prp, int *pBitBase, int type)
+{
+ ReadSample rp2;
+ uint32_t len;
+ uint32_t li;
+ int i, j;
+ int BitBase[16];
+ int bitlen;
+
+ bitlen = prp->bitlen_eff;
+
+ /*------- make map of all bit --------*/
+
+ for (i=0; i<(bitlen-1); i++) {
+ BitBase[i] = i+1;
+ }
+ rp2 = *prp;
+ SyroComp_MakeMapBuffer(map_buffer, &rp2, BitBase, (bitlen-1), type);
+ SyroComp_MakeMap_BitConv(map_buffer, (int)rp2.NumOfSample, bitlen);
+
+ /*------- Check maked map and guess bit -------*/
+ {
+ int BitBaseScore[16];
+ int maxbit, maxsc, sc;
+
+ for (i=0; i<16; i++) {
+ BitBaseScore[i] = 0;
+ }
+ for (li=0; li<prp->NumOfSample; li++) {
+ sc = map_buffer[li];
+ if (sc < 16) {
+ BitBaseScore[sc]++;
+ }
+ }
+
+ /*-- select top 4 depth -----*/
+
+ for (i=0; i<4; i++) {
+ maxsc = -1;
+ maxbit = -1;
+ for (j=0; j<bitlen; j++) {
+ if (BitBaseScore[j] > maxsc) {
+ maxsc = BitBaseScore[j];
+ maxbit = j;
+ }
+ }
+ BitBase[i] = maxbit;
+ BitBaseScore[maxbit] = -1;
+ }
+
+ /*-- sort selected bit (low->high) ----*/
+
+ for (i=0; i<3; i++) {
+ for (j=0; j<3; j++) {
+ if (BitBase[j] > BitBase[j+1]) {
+ sc = BitBase[j];
+ BitBase[j] = BitBase[j+1];
+ BitBase[j+1] = sc;
+ }
+ }
+ }
+ }
+
+ /*-----------------------------------*/
+
+ rp2 = *prp;
+ SyroComp_MakeMapBuffer(map_buffer, &rp2, BitBase, 4, type);
+ SyroComp_MakeMap_BitConv(map_buffer, (int)prp->NumOfSample, bitlen);
+
+ rp2 = *prp;
+ len = (uint32_t)SyroComp_GetCompSizeFromMap(map_buffer, &rp2, type);
+ for (i=0; i<4; i++) {
+ pBitBase[i] = BitBase[i];
+ }
+ return (int)len;
+}
+
+
+/*-----------------------------------------------------------------------------
+ make map, get size
+ -- keep prp->ptr
+ -----------------------------------------------------------------------------*/
+static int SyroComp_MakeMap(uint8_t *map_buffer, ReadSample *prp, int *pBitBase, int *ptype)
+{
+ int i;
+ int besttype;
+ int len, bestlen;
+ int BitBase[4];
+
+ bestlen = 0;
+ besttype = 0;
+
+ for (i=0; i<2; i++) {
+ len = SyroComp_MakeMap_SingleType(map_buffer, prp, BitBase, (i*2)); // type=0 or 2
+
+ if ((!bestlen) || (len < bestlen)) {
+ bestlen = len;
+ besttype = i;
+ }
+ }
+
+ if (pBitBase && ptype) {
+ bestlen = SyroComp_MakeMap_SingleType(map_buffer, prp, pBitBase, (besttype*2));
+ *ptype = (besttype ? 2 : 0);
+ }
+
+ return bestlen;
+}
+
+/*-----------------------------------------------------------------------------
+ Compress 1 block
+ ** Update prp
+ -----------------------------------------------------------------------------*/
+static int SyroComp_CompBlock(uint8_t *map_buffer, uint8_t *dest, ReadSample *prp, int *pBitBase, int type)
+{
+ int i, j, bit, prbit;
+ int bitlen;
+ int32_t dat, datlim;
+ int32_t dath[4];
+ uint8_t hd;
+ WriteBit wp;
+ int BitHead[16];
+
+ wp.ptr = dest;
+ wp.BitCount = 0;
+ wp.ByteCount = 0;
+
+ dath[0] = 0;
+ dath[1] = 0;
+ dath[2] = 0;
+ dath[3] = 0;
+
+ /*----- wrtie bit-base ------*/
+ j = 0;
+ for (i=0; i<16; i++) {
+ if (pBitBase[j]==i) {
+ BitHead[i] = j++;
+ SyroComp_WriteBit(&wp, (uint32_t)(i-1), 4);
+ } else {
+ BitHead[i] = -1;
+ }
+ }
+
+ bitlen = prp->bitlen_eff;
+ datlim = -(1<<(bitlen-1));
+
+ prbit = bitlen;
+ SyroComp_WriteBit(&wp, 3, 2);
+
+ for (i=0; i<(int)prp->NumOfSample; i++) {
+ dath[0] = SyroComp_GetPcm(prp);
+ bit = map_buffer[i];
+ if (bit != prbit) {
+ /*--- write end mark ---*/
+ SyroComp_WriteBit(&wp, (1<<(prbit-1)), prbit);
+ if (prbit==bitlen) {
+ SyroComp_WriteBit(&wp, 1, 1); /* add 1 bit when full-bit */
+ }
+ /*--- write this header ----*/
+ if (bit < bitlen) {
+ hd = (uint8_t)BitHead[bit];
+ if (bit > prbit) {
+ hd--;
+ }
+ } else {
+ hd = 3;
+ }
+ SyroComp_WriteBit(&wp, hd, 2);
+ prbit = bit;
+ }
+ if ((prbit < bitlen) && type) {
+ dat = dath[0] - (dath[1]*2 - dath[2]);
+ } else {
+ dat = dath[0];
+ }
+ SyroComp_WriteBit(&wp, (uint32_t)dat, prbit);
+ if ((prbit == bitlen) && (dat == datlim)) {
+ SyroComp_WriteBit(&wp, 0, 1);
+ }
+ dath[3] = dath[2];
+ dath[2] = dath[1];
+ dath[1] = dath[0];
+ }
+
+ SyroComp_WriteBit(&wp, (1<<(prbit-1)), prbit); /* EndMark */
+ if (prbit == bitlen) {
+ SyroComp_WriteBit(&wp, 1, 1); /* add 1 bit when full-bit */
+ }
+
+ if (wp.BitCount) {
+ SyroComp_WriteBit(&wp, 0, (8 - wp.BitCount));
+ }
+
+ return wp.ByteCount;
+}
+
+
+/*======================================================================
+ Syro Get Sample
+ ======================================================================*/
+uint32_t SyroComp_GetCompSize(const uint8_t *psrc, uint32_t num_of_sample,
+ uint32_t quality, Endian sample_endian)
+{
+ ReadSample rp;
+ uint32_t num_of_thissample;
+ uint32_t allsize_byte;
+ uint32_t thissize_bit;
+ uint8_t *map_buffer;
+
+ map_buffer = malloc(VOLCASAMPLE_COMP_BLOCK_LEN);
+ if (!map_buffer) {
+ return 0;
+ }
+
+ rp.ptr = psrc;
+ rp.bitlen_eff = (int)quality;
+ rp.SampleEndian = sample_endian;
+
+ allsize_byte = 0;
+
+ for (;;) {
+ num_of_thissample = VOLCASAMPLE_COMP_BLOCK_LEN;
+ if (num_of_thissample > num_of_sample) {
+ num_of_thissample = num_of_sample;
+ }
+ rp.NumOfSample = num_of_thissample;
+ thissize_bit = (uint32_t)SyroComp_MakeMap(map_buffer, &rp, NULL, NULL);
+
+ if ((!thissize_bit) || (thissize_bit >= (quality * num_of_thissample))) {
+ //----- use liner ----
+ thissize_bit = (quality * num_of_thissample);
+ }
+ allsize_byte += ((thissize_bit + 7) / 8);
+
+ allsize_byte += 6; //--- for Header & CRC -----
+
+ rp.ptr += (num_of_thissample * 2);
+ num_of_sample -= num_of_thissample;
+
+ if (!num_of_sample) {
+ break;
+ }
+ }
+
+ free(map_buffer);
+
+ return allsize_byte;
+}
+
+
+/*=============================================================================
+ Compress Block
+ psrc = pointer to source sample.
+ pdest = pointer to store compressed data.
+ num_of_sample = number of sample.
+ quality = number of effective bit(8~16).
+ sample_endian = specific endian of source sample(LittleEndian or BigEndian).
+ =============================================================================*/
+uint32_t SyroComp_Comp(const uint8_t *psrc, uint8_t *pdest, int num_of_sample,
+ int quality, Endian sample_endian)
+{
+ ReadSample rp;
+ int BitBase[4];
+ int i;
+ int srccount, count;
+ int num_of_thissample;
+ int prlen;
+ int type;
+ int32_t dat;
+ uint8_t *map_buffer;
+
+ map_buffer = malloc(VOLCASAMPLE_COMP_BLOCK_LEN);
+ if (!map_buffer) {
+ return 0;
+ }
+
+ rp.bitlen_eff = quality;
+ rp.SampleEndian = sample_endian;
+ rp.ptr = psrc;
+
+ count = 0;
+ srccount = 0;
+
+ for (;;) {
+ /*------- decide block length ------*/
+ num_of_thissample = VOLCASAMPLE_COMP_BLOCK_LEN;
+ if (num_of_thissample > num_of_sample) {
+ num_of_thissample = num_of_sample;
+ }
+ rp.NumOfSample = (uint32_t)num_of_thissample;
+ rp.sum = 0;
+
+ prlen = SyroComp_MakeMap(map_buffer, &rp, BitBase, &type);
+
+ if (prlen && (prlen < (num_of_thissample*quality))) {
+ /*----- compressible ------*/
+ *pdest++ = (uint8_t)(num_of_thissample>>8) | (uint8_t)(type<<5);
+ *pdest++ = (uint8_t)num_of_thissample;
+ prlen = SyroComp_CompBlock(map_buffer, pdest+4, &rp, BitBase, type);
+ *pdest++ = (uint8_t)(prlen>>8);
+ *pdest++ = (uint8_t)prlen;
+ *pdest++ = (uint8_t)(rp.sum >> 8);
+ *pdest++ = (uint8_t)rp.sum;
+ count += (prlen+6);
+ pdest += prlen;
+ } else {
+ /*----- copy without compression ------*/
+ *pdest++ = (uint8_t)(0xe0 | (num_of_thissample>>8));
+ *pdest++ = (uint8_t)num_of_thissample;
+ *pdest++ = (uint8_t)(num_of_thissample>>7);
+ *pdest++ = (uint8_t)(num_of_thissample<<1);
+ {
+ WriteBit wb;
+ wb.ptr = (pdest+2);
+ wb.BitCount = 0;
+ wb.ByteCount = 0;
+
+ for (i=0; i<num_of_thissample; i++) {
+ dat = SyroComp_GetPcm(&rp);
+ SyroComp_WriteBit(&wb, (uint32_t)dat, quality);
+ }
+ if (wb.BitCount) {
+ SyroComp_WriteBit(&wb, 0, (8-wb.BitCount));
+ }
+ *pdest++ = (uint8_t)(rp.sum >> 8);
+ *pdest++ = (uint8_t)rp.sum;
+
+ prlen = wb.ByteCount;
+ pdest += prlen;
+ count += (prlen+6);
+ }
+ }
+ num_of_sample -= num_of_thissample;
+ srccount += num_of_thissample;
+ if (!num_of_sample) {
+ break;
+ }
+ }
+
+ free(map_buffer);
+
+ return (uint32_t)count;
+}
+
+
+
+
+
--- /dev/null
+++ b/korg_syro_comp.h
@@ -1,0 +1,24 @@
+#ifndef KORG_SYRO_COMP_H__
+#define KORG_SYRO_COMP_H__
+
+#include "korg_syro_type.h"
+
+#define VOLCASAMPLE_COMP_BLOCK_LEN 0x800
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+uint32_t SyroComp_GetCompSize(const uint8_t *psrc, uint32_t num_of_sample,
+ uint32_t quality, Endian sample_endian);
+
+uint32_t SyroComp_Comp(const uint8_t *psrc, uint8_t *pdest, int num_of_sample,
+ int quality, Endian sample_endian);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null
+++ b/korg_syro_func.c
@@ -1,0 +1,293 @@
+/************************************************************************
+ KORG SYRO func
+ ***********************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include "korg_syro_type.h"
+#include "korg_syro_func.h"
+
+static const uint8_t ecc_table[256] = {
+ 0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00,
+ 0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
+ 0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
+ 0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
+ 0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
+ 0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
+ 0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
+ 0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
+ 0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A,
+ 0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F,
+ 0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C,
+ 0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69,
+ 0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03,
+ 0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66,
+ 0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65,
+ 0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00
+};
+
+static const uint16_t crc16_table[] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+static const int16_t sin_table[] = {
+ 0, 23169, 32767, 23169, 0, -23169, -32767, -23169
+};
+
+/*----------------------------------------------------------------
+ Calculate CRC16
+ ----------------------------------------------------------------*/
+uint16_t SyroFunc_CalculateCrc16(uint8_t *pSrc, int size)
+{
+ int i;
+ uint16_t dat, crc;
+
+ crc = 0xffff;
+
+ for (i=0; i<size; i++) {
+ dat = *pSrc++;
+ crc = crc16_table[(crc >> 8) ^ dat] ^ ((crc&0xff)<<8);
+ }
+ return crc;
+}
+
+/*----------------------------------------------------------------
+ Calculate ECC
+ ----------------------------------------------------------------*/
+uint32_t SyroFunc_CalculateEcc(uint8_t *pSrc, int size)
+{
+ int i;
+ uint8_t ecc_reg1, ecc_reg2, ecc_reg3;
+ uint8_t ecc1, ecc2, bitpat_a, bitpat_b;
+ uint8_t ci;
+ uint32_t ecc;
+
+ ecc_reg1 = 0;
+ ecc_reg2 = 0;
+ ecc_reg3 = 0;
+
+ for (i=0; i<size; i++) {
+ ci = ecc_table[pSrc[i]];
+ ecc_reg1 ^= ci;
+ if (ci & 0x40) {
+ ecc_reg3 ^= (uint8_t)i;
+ ecc_reg2 ^= ~((uint8_t)i);
+ }
+ }
+
+ ecc1 = 0;
+ ecc2 = 0;
+ bitpat_a = 0x80;
+
+ bitpat_b = 0x80;
+ for (i=0; i<4; i++) {
+ if (ecc_reg3 & bitpat_a) {
+ ecc1 |= bitpat_b;
+ }
+ bitpat_b >>= 1;
+ if (ecc_reg2 & bitpat_a) {
+ ecc1 |= bitpat_b;
+ }
+ bitpat_b >>= 1;
+ bitpat_a >>= 1;
+ }
+
+ bitpat_b = 0x80;
+ for (i=0; i<4; i++) {
+ if (ecc_reg3 & bitpat_a) {
+ ecc2 |= bitpat_b;
+ }
+ bitpat_b >>= 1;
+ if (ecc_reg2 & bitpat_a) {
+ ecc2 |= bitpat_b;
+ }
+ bitpat_b >>= 1;
+ bitpat_a >>= 1;
+ }
+
+ ecc_reg1 = (ecc_reg1 << 2) | 3;
+
+ ecc = ecc_reg1;
+ ecc <<= 8;
+ ecc |= ecc2;
+ ecc <<= 8;
+ ecc |= ecc1;
+
+ return ecc;
+}
+
+/*-----------------------------------------------------------------------
+ Set Tx Size
+ -----------------------------------------------------------------------*/
+void SyroFunc_SetTxSize(uint8_t *ptr, uint32_t size, int num_of_bytes)
+{
+ int i;
+
+ for (i=0; i<num_of_bytes; i++) {
+ *ptr++ = (uint8_t)size;
+ size >>= 8;
+ }
+}
+
+/*----------------------------------------------------------------
+ Get sin value
+ ----------------------------------------------------------------*/
+static int16_t SyroFunc_GetSinValue(int phase, bool bData)
+{
+ int32_t ret;
+
+ ret = sin_table[phase];
+
+ if (bData) {
+ if (ret > 0) {
+ ret = 32767 - ret;
+ ret = ((ret * ret) / 32767);
+ ret = 32767 - ret;
+ } else if (ret < 0) {
+ ret += 32767;
+ ret = ((ret * ret) / 32767);
+ ret -= 32767;
+ }
+ }
+
+ return (int16_t)ret;
+}
+
+/*-----------------------------------------------------------------------
+ Generate Single Sycle
+ -----------------------------------------------------------------------*/
+void SyroFunc_GenerateSingleCycle(SyroChannel *psc, int write_page, uint8_t dat, bool block)
+{
+ int i, phase_org, phase;
+ int32_t dat1, dat2;
+ int vol, dlt;
+ int write_pos, write_pos_last;
+
+ write_pos = write_page * KORGSYRO_QAM_CYCLE;
+ write_pos_last = write_pos ? (write_pos - 1) : (KORGSYRO_NUM_OF_CYCLE_BUF - 1);
+
+ phase_org = (dat >> 1) & 3;
+ phase = phase_org * (KORGSYRO_QAM_CYCLE / 4);
+ vol = (dat & 1);
+ vol = vol ? 16 : 4;
+
+ for (i=0; i<KORGSYRO_QAM_CYCLE; i++) {
+ dat1 = SyroFunc_GetSinValue(phase, block);
+ dat1 = (dat1 * vol) / 24;
+ if (!i) {
+ if (phase_org != psc->LastPhase) {
+ if (((psc->LastPhase & 1) && (phase_org & 1)) ||
+ (((psc->LastPhase + 1) & 3) == phase_org))
+ {
+ dat2 = psc->CycleSample[write_pos_last];
+ dlt = dat1 - dat2;
+ dlt /= 3;
+ dat1 -= dlt;
+ dat2 += dlt;
+ psc->CycleSample[write_pos_last] = (int16_t)dat2;
+ }
+ }
+ }
+
+ psc->CycleSample[write_pos++] = (int16_t)dat1;
+ if ((++phase) == KORGSYRO_QAM_CYCLE) {
+ phase = 0;
+ }
+ }
+ psc->LastPhase = phase_org;
+}
+
+/*-----------------------------------------------------------------------
+ Smooth Start Mark
+ -----------------------------------------------------------------------*/
+static void SyroFunc_SmoothStartMark(SyroChannel *psc, int write_page)
+{
+ int write_pos, write_pos_last;
+ int32_t dat1, dat2, dat3, avg;
+
+ write_pos = write_page * KORGSYRO_QAM_CYCLE;
+ write_pos_last = write_pos ? (write_pos - 1) : (KORGSYRO_NUM_OF_CYCLE_BUF - 1);
+
+ dat1 = psc->CycleSample[write_pos_last];
+ dat2 = psc->CycleSample[write_pos];
+ dat3 = psc->CycleSample[write_pos+1];
+
+ avg = (dat1 + dat2 + dat3) / 3;
+
+ dat1 = (dat1 + avg) / 2;
+ dat2 = (dat2 + avg) / 2;
+ dat3 = (dat3 + avg) / 2;
+
+ psc->CycleSample[write_pos_last] = (int16_t)dat1;
+ psc->CycleSample[write_pos] = (int16_t)dat2;
+ psc->CycleSample[write_pos+1] = (int16_t)dat3;
+}
+
+/*-----------------------------------------------------------------------
+ Generate Gap
+ -----------------------------------------------------------------------*/
+void SyroFunc_MakeGap(SyroChannel *psc, int write_page)
+{
+ uint8_t ch;
+
+ for (ch=0; ch<KORGSYRO_NUM_OF_CHANNEL; ch++) {
+ SyroFunc_GenerateSingleCycle(&psc[ch], write_page, 1, false);
+ }
+}
+
+/*-----------------------------------------------------------------------
+ Generate Start Mark
+ -----------------------------------------------------------------------*/
+void SyroFunc_MakeStartMark(SyroChannel *psc, int write_page)
+{
+ uint8_t ch;
+
+ for (ch=0; ch<KORGSYRO_NUM_OF_CHANNEL; ch++) {
+ SyroFunc_GenerateSingleCycle(&psc[ch], write_page, 5, false);
+ SyroFunc_SmoothStartMark(&psc[ch], write_page);
+ }
+}
+
+/*-----------------------------------------------------------------------
+ Generate Channel Info
+ -----------------------------------------------------------------------*/
+void SyroFunc_MakeChannelInfo(SyroChannel *psc, int write_page)
+{
+ uint8_t ch;
+
+ for (ch=0; ch<KORGSYRO_NUM_OF_CHANNEL; ch++) {
+ SyroFunc_GenerateSingleCycle(&psc[ch], write_page, ch, true);
+ }
+}
+
+
--- /dev/null
+++ b/korg_syro_func.h
@@ -1,0 +1,46 @@
+/*
+ * korg_syro_func.h - KORG SYRO SDK
+ * Copyright (C) 2014, KORG Inc. All rights reserved.
+ *
+ * This file is part of SYRO SDK.
+ *
+ * This software may be modified and distributed under the terms
+ * of the BSD license. See the COPYING file for details.
+ */
+#ifndef KORG_SYRO_FUNC_H__
+#define KORG_SYRO_FUNC_H__
+
+#include "korg_syro_type.h"
+
+#define KORGSYRO_NUM_OF_CHANNEL 2
+
+#define KORGSYRO_QAM_CYCLE 8
+#define KORGSYRO_NUM_OF_CYCLE 2
+#define KORGSYRO_NUM_OF_CYCLE_BUF (KORGSYRO_QAM_CYCLE * KORGSYRO_NUM_OF_CYCLE)
+
+typedef struct {
+ int16_t CycleSample[KORGSYRO_NUM_OF_CYCLE_BUF];
+ int LastPhase;
+ int32_t Lpf_z;
+} SyroChannel;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+uint16_t SyroFunc_CalculateCrc16(uint8_t *pSrc, int size);
+uint32_t SyroFunc_CalculateEcc(uint8_t *pSrc, int size);
+void SyroFunc_SetTxSize(uint8_t *ptr, uint32_t size, int num_of_bytes);
+
+void SyroFunc_GenerateSingleCycle(SyroChannel *psc, int write_page, uint8_t dat, bool block);
+void SyroFunc_MakeGap(SyroChannel *psc, int write_page);
+void SyroFunc_MakeStartMark(SyroChannel *psc, int write_page);
+void SyroFunc_MakeChannelInfo(SyroChannel *psc, int write_page);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null
+++ b/korg_syro_type.h
@@ -1,0 +1,46 @@
+#ifndef KORG_SYRO_TYPE_H__
+#define KORG_SYRO_TYPE_H__
+
+#ifndef _MSC_VER
+
+#include <stdint.h>
+
+#else // #ifndef _MSC_VER
+
+#ifndef uint8_t
+typedef unsigned char uint8_t;
+#endif
+#ifndef int8_t
+typedef signed char int8_t;
+#endif
+
+#ifndef uint16_t
+typedef unsigned short uint16_t;
+#endif
+#ifndef int16_t
+typedef short int16_t;
+#endif
+
+#ifndef uint32_t
+typedef unsigned long uint32_t;
+#endif
+#ifndef int32_t
+typedef long int32_t;
+#endif
+
+#endif // #ifndef _MSC_VER
+
+#ifndef __cplusplus
+#ifndef bool
+typedef int bool;
+#endif
+#ifndef true
+#define true (1)
+#endif
+#ifndef false
+#define false (0)
+#endif
+#endif // #ifndef __cplusplus
+
+#endif // #ifndef KORG_SYRO_VOLCASAMPLE_H__
+
--- /dev/null
+++ b/korg_syro_volcasample.c
@@ -1,0 +1,791 @@
+/************************************************************************
+ SYRO for volca sample
+ ***********************************************************************/
+#include <stdlib.h>
+#include <string.h>
+#include "korg_syro_type.h"
+#include "korg_syro_volcasample.h"
+#include "korg_syro_func.h"
+#include "korg_syro_comp.h"
+
+#define NUM_OF_DATA_MAX (VOLCASAMPLE_NUM_OF_PATTERN + VOLCASAMPLE_NUM_OF_SAMPLE)
+#define VOLCA_SAMPLE_FS 31250
+#define SYRO_MANAGE_HEADER 0x47524F4B
+#define ALL_INFO_SIZE 0x4000
+
+#define BLOCK_SIZE 256
+#define BLOCK_PER_SECTOR 256
+#define BLOCK_PER_SUBSECTOR 16
+#define SUBSECTOR_SIZE (BLOCK_SIZE * BLOCK_PER_SUBSECTOR)
+
+#define LPF_FEEDBACK_LEVEL 0x2000
+
+#define NUM_OF_GAP_HEADER_CYCLE 10000
+#define NUM_OF_GAP_CYCLE 35
+#define NUM_OF_GAP_F_CYCLE 1000
+#define NUM_OF_GAP_FOOTER_CYCLE 3000
+#define NUM_OF_GAP_3S_CYCLE 15000
+
+#define NUM_OF_FRAME__GAP_HEADER (NUM_OF_GAP_HEADER_CYCLE * KORGSYRO_QAM_CYCLE)
+#define NUM_OF_FRAME__GAP (NUM_OF_GAP_CYCLE * KORGSYRO_QAM_CYCLE)
+#define NUM_OF_FRAME__GAP_F (NUM_OF_GAP_F_CYCLE * KORGSYRO_QAM_CYCLE)
+#define NUM_OF_FRAME__GAP_3S (NUM_OF_GAP_3S_CYCLE * KORGSYRO_QAM_CYCLE)
+#define NUM_OF_FRAME__GAP_FOOTER (NUM_OF_GAP_FOOTER_CYCLE * KORGSYRO_QAM_CYCLE)
+#define NUM_OF_FRAME__HEADER (49 * KORGSYRO_QAM_CYCLE)
+#define NUM_OF_FRAME__BLOCK (352 * KORGSYRO_QAM_CYCLE)
+
+#define TXHEADER_STR_LEN 16
+#define TXHEADER_STR "KORG SYSTEM FILE"
+#define TXHEADER_DEVICE_ID 0xff0033b8 // volca sample
+#define TXHEADER_BLOCK_ALL 0x01
+#define TXHEADER_BLOCK_ALL_COMPRESS 0x03
+#define TXHEADER_BLOCK_SAMPLE_LINER 0x10
+#define TXHEADER_BLOCK_PATTERN 0x20
+#define TXHEADER_BLOCK_SAMPLE_COMPRESS 0x30
+
+typedef enum {
+ TaskStatus_Gap = 0,
+ TaskStatus_StartMark,
+ TaskStatus_ChannelInfo,
+ TaskStatus_Data,
+ TaskStatus_Gap_Footer,
+ TaskStatus_End = -1
+} SyroTaskStatus;
+
+typedef struct {
+ uint8_t Header[TXHEADER_STR_LEN];
+ uint32_t DeviceID;
+ uint8_t BlockCode;
+ uint8_t Num;
+
+ uint8_t Misc[2];
+ uint8_t Size[4];
+
+ uint16_t m_Reserved;
+ uint16_t m_Speed;
+} SyroTxHeader;
+
+typedef struct {
+ uint32_t Header;
+ uint32_t Flags;
+ SyroTaskStatus TaskStatus;
+ int TaskCount;
+
+ //---- Manage source data(all) -----
+ int NumOfData;
+ int CurData;
+
+ //---- Manage source data(this) -----
+ const uint8_t *pSrcData;
+ int DataCount;
+ int DataSize;
+ uint32_t EraseAlign;
+ uint32_t EraseLength;
+ uint32_t EraseCount;
+ bool IsCompData;
+ int CompBlockPos;
+ uint32_t BlockLen1st;
+
+ Endian SampleEndian;
+
+ //---- Manage output data -----
+ uint8_t TxBlock[BLOCK_SIZE];
+ int TxBlockSize;
+ int TxBlockPos;
+
+ uint32_t PoolData;
+ int PoolDataBit;
+
+ bool UseEcc;
+ uint32_t EccData;
+ bool UseCrc;
+ uint32_t CrcData;
+
+ SyroChannel Channel[KORGSYRO_NUM_OF_CHANNEL];
+ int CyclePos;
+ int FrameCountInCycle;
+
+ int LongGapCount; // Debug Put
+} SyroManage;
+
+typedef struct {
+ SyroData Data;
+ uint8_t *comp_buf;
+ uint32_t comp_size;
+} SyroManageSingle;
+
+/*-----------------------------------------------------------------------
+ Setup Next Data
+ -----------------------------------------------------------------------*/
+static void SyroVolcaSample_SetupNextData(SyroManage *psm)
+{
+ SyroManageSingle *psms;
+ SyroTxHeader *psth;
+ uint8_t block = 0;
+
+ psms = (SyroManageSingle *)(psm+1);
+ psms += psm->CurData;
+
+ //----- Setup Tx Header ----
+ psth = (SyroTxHeader *)psm->TxBlock;
+
+ memset((uint8_t *)psth, 0, sizeof(SyroTxHeader));
+ memcpy(psth->Header, TXHEADER_STR, TXHEADER_STR_LEN);
+ psth->DeviceID = TXHEADER_DEVICE_ID;
+
+ psth->Num = (uint8_t)psms->Data.Number;
+
+ psm->SampleEndian = LittleEndian;
+ psm->TxBlockSize = sizeof(SyroTxHeader);
+
+ psm->pSrcData = psms->Data.pData;
+ psm->DataSize = psms->Data.Size;
+ psm->DataCount = 0;
+ psm->IsCompData = false;
+ psm->CompBlockPos = 0;
+ psm->EraseAlign = 0;
+ psm->EraseLength = 0;
+
+ switch (psms->Data.DataType) {
+ case DataType_Sample_All:
+ case DataType_Sample_AllCompress:
+ if (psms->Data.DataType == DataType_Sample_All) {
+ block = TXHEADER_BLOCK_ALL;
+ psth->Misc[0] = 0xff;
+ } else {
+ block = TXHEADER_BLOCK_ALL_COMPRESS;
+ psm->pSrcData = psms->comp_buf;
+ psm->DataSize = psms->comp_size;
+ psm->IsCompData = true;
+ psth->Misc[0] = (uint8_t)psms->Data.Quality;
+ psm->BlockLen1st = ALL_INFO_SIZE;
+ }
+ if ((psm->CurData+1) < psm->NumOfData) {
+ block++; //----- Set continue
+ }
+
+ SyroFunc_SetTxSize(psth->Size, psms->Data.Size, 4);
+ psth->Misc[1] = 0xff;
+ psth->Num = 0xff;
+ psm->EraseAlign = (BLOCK_PER_SECTOR * BLOCK_SIZE);
+ psm->EraseLength = NUM_OF_GAP_3S_CYCLE;
+ psm->EraseCount = (psms->Data.Size + psm->EraseAlign - 1) / psm->EraseAlign;
+
+ break;
+
+ case DataType_Sample_Liner:
+ case DataType_Sample_Compress:
+ if (psms->Data.DataType == DataType_Sample_Liner) {
+ block = TXHEADER_BLOCK_SAMPLE_LINER;
+ } else {
+ block = TXHEADER_BLOCK_SAMPLE_COMPRESS;
+ psm->pSrcData = psms->comp_buf;
+ psm->DataSize = psms->comp_size;
+ psm->IsCompData = true;
+ psth->Misc[0] = (uint8_t)psms->Data.Quality;
+ psm->BlockLen1st = 0;
+ }
+
+ if ((psm->CurData+1) < psm->NumOfData) {
+ block |= 1; //----- Set continue bit
+ }
+ SyroFunc_SetTxSize(psth->Size, psms->Data.Size, 4);
+
+ psth->m_Reserved = 0xffff;
+ psth->m_Speed = (uint16_t)(psms->Data.Fs * 0x4000 / VOLCA_SAMPLE_FS);
+
+ psm->SampleEndian = psms->Data.SampleEndian;
+
+ psm->EraseAlign = (SUBSECTOR_SIZE - 2);
+ psm->EraseLength = NUM_OF_GAP_F_CYCLE;
+ psm->EraseCount = (psms->Data.Size + psm->EraseAlign - 1) / psm->EraseAlign;
+
+ break;
+
+ case DataType_Sample_Erase:
+ block = TXHEADER_BLOCK_SAMPLE_LINER;
+ if ((psm->CurData+1) < psm->NumOfData) {
+ block |= 1; //----- Set continue bit
+ }
+ psth->m_Reserved = 0xffff;
+ psth->m_Speed = 0x4000;
+
+ psm->pSrcData = NULL;
+ psm->DataSize = 0;
+ break;
+
+ case DataType_Pattern:
+ block = TXHEADER_BLOCK_PATTERN;
+ if ((psm->CurData+1) < psm->NumOfData) {
+ block |= 1; //----- Set continue bit
+ }
+ SyroFunc_SetTxSize(psth->Size, psm->DataSize, 4);
+
+ break;
+
+ default:
+ break;
+ }
+ psth->BlockCode = block;
+
+ psm->TaskStatus = TaskStatus_Gap;
+ psm->TaskCount = NUM_OF_GAP_HEADER_CYCLE;
+}
+
+
+/*-----------------------------------------------------------------------
+ Setup by TxBlock
+ -----------------------------------------------------------------------*/
+static void SyroVolcaSample_SetupBlock(SyroManage *psm)
+{
+ bool use_ecc;
+
+ use_ecc = (psm->TxBlockSize == BLOCK_SIZE) ? true : false;
+
+ psm->TxBlockPos = 0;
+ psm->TaskCount = psm->TxBlockSize;
+ psm->UseEcc = use_ecc;
+ psm->UseCrc = true;
+
+ psm->CrcData = SyroFunc_CalculateCrc16(psm->TxBlock, psm->TxBlockSize);
+ if (use_ecc) {
+ psm->EccData = SyroFunc_CalculateEcc(psm->TxBlock, psm->TxBlockSize);
+ }
+
+ psm->PoolData = 0xa9; // Block Start Code
+ psm->PoolDataBit = 8;
+}
+
+/************************************************************************
+ Internal Functions (Output Syro Data)
+ ***********************************************************************/
+/*-----------------------------------------------------------------------
+ Generate Data
+ ret : true if block is end.
+ -----------------------------------------------------------------------*/
+static bool SyroVolcaSample_MakeData(SyroManage *psm, int write_page)
+{
+ int ch, bit;
+ uint32_t dat;
+ bool data_end;
+
+ data_end = false;
+
+ //------ Supply Data/Ecc/Crc ------
+ if (psm->PoolDataBit < (3 * KORGSYRO_NUM_OF_CHANNEL)) {
+ if (psm->TaskCount) {
+ dat = psm->TxBlock[psm->TxBlockPos++];
+ bit = 8;
+ psm->TaskCount--;
+ } else if (psm->UseEcc) {
+ dat = psm->EccData;
+ bit = 24;
+ psm->UseEcc = false;
+ } else if (psm->UseCrc) {
+ dat = psm->CrcData;
+ bit = 16;
+ psm->UseCrc = false;
+ } else {
+ dat = 0;
+ bit = (3 * KORGSYRO_NUM_OF_CHANNEL) - psm->PoolDataBit;
+ data_end = true;
+ }
+ psm->PoolData |= (dat << psm->PoolDataBit);
+ psm->PoolDataBit += bit;
+ }
+
+ //------ Make Cycle ------
+ for (ch=0; ch<KORGSYRO_NUM_OF_CHANNEL; ch++) {
+ SyroFunc_GenerateSingleCycle(&psm->Channel[ch], write_page, (psm->PoolData & 7), true);
+ psm->PoolData >>= 3;
+ psm->PoolDataBit -= 3;
+ }
+
+ return data_end;
+}
+
+/*-----------------------------------------------------------------------
+ Nake Next Cycle
+ -----------------------------------------------------------------------*/
+static void SyroVolcaSample_CycleHandler(SyroManage *psm)
+{
+ int write_page;
+ uint32_t comp_len, org_len;
+
+ write_page = (psm->CyclePos / KORGSYRO_QAM_CYCLE) ^ 1;
+
+ switch (psm->TaskStatus) {
+ case TaskStatus_Gap:
+ SyroFunc_MakeGap(psm->Channel, write_page);
+ if (!(--psm->TaskCount)) {
+ psm->TaskStatus = TaskStatus_StartMark;
+ SyroVolcaSample_SetupBlock(psm);
+ }
+ break;
+
+ case TaskStatus_StartMark:
+ SyroFunc_MakeStartMark(psm->Channel, write_page);
+ psm->TaskStatus = TaskStatus_ChannelInfo;
+ break;
+
+ case TaskStatus_ChannelInfo:
+ SyroFunc_MakeChannelInfo(psm->Channel, write_page);
+ psm->TaskStatus = TaskStatus_Data;
+ break;
+
+ case TaskStatus_Data:
+ if (SyroVolcaSample_MakeData(psm, write_page)) {
+ if (psm->DataCount < psm->DataSize) {
+ int pos, size;
+
+ size = (psm->DataSize - psm->DataCount);
+ if (size >= BLOCK_SIZE) {
+ size = BLOCK_SIZE;
+ } else {
+ memset(psm->TxBlock, 0, BLOCK_SIZE);
+ }
+ if (psm->SampleEndian == LittleEndian) {
+ memcpy(psm->TxBlock, (psm->pSrcData+psm->DataCount), size);
+ } else {
+ for (pos=0; pos<size; pos+=2) {
+ psm->TxBlock[pos] = psm->pSrcData[psm->DataCount+pos+1];
+ psm->TxBlock[pos+1] = psm->pSrcData[psm->DataCount+pos];
+ }
+ }
+ psm->TaskStatus = TaskStatus_Gap;
+ psm->TaskCount = NUM_OF_GAP_CYCLE;
+
+ if (!psm->IsCompData) {
+ if (psm->EraseAlign && (!(psm->DataCount % psm->EraseAlign))) {
+ psm->TaskCount = psm->EraseLength;
+ }
+ } else {
+ if (psm->EraseCount && (psm->CompBlockPos < (psm->DataCount+size))) {
+
+ psm->TaskCount = psm->EraseLength;
+ psm->EraseCount--;
+ org_len = 0;
+
+ for (;;) {
+ if (psm->BlockLen1st) {
+ psm->CompBlockPos += psm->BlockLen1st;
+ org_len += psm->BlockLen1st;
+ psm->BlockLen1st = 0;
+ } else {
+ comp_len = (uint32_t)psm->pSrcData[psm->CompBlockPos+2];
+ comp_len <<= 8;
+ comp_len |= (uint32_t)psm->pSrcData[psm->CompBlockPos+3];
+ psm->CompBlockPos += (comp_len+6);
+ org_len += (VOLCASAMPLE_COMP_BLOCK_LEN * 2);
+ }
+ if ((psm->CompBlockPos >= psm->DataSize) ||
+ (org_len >= psm->EraseAlign))
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ psm->TxBlockSize = BLOCK_SIZE;
+ psm->DataCount += size;
+
+ } else {
+ psm->CurData++;
+ if (psm->CurData < psm->NumOfData) {
+ SyroVolcaSample_SetupNextData(psm);
+ } else {
+ psm->TaskStatus = TaskStatus_Gap_Footer;
+ psm->TaskCount = NUM_OF_GAP_FOOTER_CYCLE;
+ }
+ }
+ }
+ break;
+
+ case TaskStatus_Gap_Footer:
+ SyroFunc_MakeGap(psm->Channel, write_page);
+ if (!(--psm->TaskCount)) {
+ psm->TaskStatus = TaskStatus_End;
+ }
+ break;
+
+ default: // case TaskStatus_End:
+ return;
+ }
+
+ psm->FrameCountInCycle += KORGSYRO_QAM_CYCLE;
+}
+
+/*-----------------------------------------------------------------------
+ Get Ch Sample
+ -----------------------------------------------------------------------*/
+static int16_t SyroVolcaSample_GetChSample(SyroManage *psm, int ch)
+{
+ int32_t dat;
+
+ dat = (int32_t)psm->Channel[ch].CycleSample[psm->CyclePos];
+
+ //----- LPF -----*/
+ dat = ((dat * (0x10000 - LPF_FEEDBACK_LEVEL)) +
+ (psm->Channel[ch].Lpf_z * LPF_FEEDBACK_LEVEL));
+ dat /= 0x10000;
+ psm->Channel[ch].Lpf_z = dat;
+
+ return (int16_t)dat;
+}
+
+/*-----------------------------------------------------------------------
+ Get Frame Size (union)
+ -----------------------------------------------------------------------*/
+static uint32_t SyroVolcaSample_GetFrameSize(int num_of_block)
+{
+ uint32_t size;
+
+ size = NUM_OF_FRAME__GAP_HEADER;
+ size += NUM_OF_FRAME__HEADER;
+
+ size += (NUM_OF_FRAME__GAP + NUM_OF_FRAME__BLOCK) * num_of_block;
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ Get Frame Size (Pattern)
+ -----------------------------------------------------------------------*/
+static uint32_t SyroVolcaSample_GetFrameSize_Pattern(void)
+{
+ return SyroVolcaSample_GetFrameSize((VOLCASAMPLE_PATTERN_SIZE + BLOCK_SIZE - 1) / BLOCK_SIZE);
+}
+
+/*-----------------------------------------------------------------------
+ Get Frame Size (Sample)
+ -----------------------------------------------------------------------*/
+static uint32_t SyroVolcaSample_GetFrameSize_Sample(uint32_t byte_size)
+{
+ uint32_t size;
+ uint32_t num_of_block;
+
+ num_of_block = (byte_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ size = SyroVolcaSample_GetFrameSize(num_of_block);
+
+ num_of_block = (byte_size + SUBSECTOR_SIZE - 3) / (SUBSECTOR_SIZE - 2);
+ size += (NUM_OF_FRAME__GAP_F - NUM_OF_FRAME__GAP) * num_of_block;
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ Get Frame Size (Sample, Compress)
+ -----------------------------------------------------------------------*/
+static uint32_t SyroVolcaSample_GetFrameSize_Sample_Comp(SyroData *pdata)
+{
+ uint32_t size, comp_size;
+ uint32_t num_of_block;
+
+ comp_size = SyroComp_GetCompSize(
+ pdata->pData,
+ (pdata->Size / 2),
+ pdata->Quality,
+ pdata->SampleEndian
+ );
+
+ //----- get frame size from compressed size.
+ num_of_block = (comp_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ size = SyroVolcaSample_GetFrameSize(num_of_block);
+
+ //----- get gap size from original size.
+ num_of_block = (pdata->Size + SUBSECTOR_SIZE - 3) / (SUBSECTOR_SIZE - 2);
+ size += (NUM_OF_FRAME__GAP_F - NUM_OF_FRAME__GAP) * num_of_block;
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ Get Frame Size (All)
+ -----------------------------------------------------------------------*/
+static uint32_t SyroVolcaSample_GetFrameSize_All(uint32_t byte_size)
+{
+ uint32_t size;
+ uint32_t num_of_block;
+
+ num_of_block = (byte_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ size = SyroVolcaSample_GetFrameSize(num_of_block);
+
+ num_of_block = (num_of_block + BLOCK_PER_SECTOR - 1) / BLOCK_PER_SECTOR;
+ size += (NUM_OF_FRAME__GAP_3S - NUM_OF_FRAME__GAP) * num_of_block;
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ Get Frame Size (All, Comp)
+ -----------------------------------------------------------------------*/
+static uint32_t SyroVolcaSample_GetFrameSize_AllComp(SyroData *pdata)
+{
+ uint32_t size, comp_size;
+ uint32_t num_of_block;
+
+ if (pdata->Size == ALL_INFO_SIZE) {
+ return SyroVolcaSample_GetFrameSize_All(pdata->Size);
+ }
+
+ comp_size = SyroComp_GetCompSize(
+ (pdata->pData + ALL_INFO_SIZE),
+ ((pdata->Size - ALL_INFO_SIZE) / 2),
+ pdata->Quality,
+ LittleEndian
+ );
+
+ comp_size += ALL_INFO_SIZE;
+ num_of_block = (comp_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ size = SyroVolcaSample_GetFrameSize(num_of_block);
+
+ num_of_block = (pdata->Size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ num_of_block = (num_of_block + BLOCK_PER_SECTOR - 1) / BLOCK_PER_SECTOR;
+ size += (NUM_OF_FRAME__GAP_3S - NUM_OF_FRAME__GAP) * num_of_block;
+
+ return size;
+}
+
+/*-----------------------------------------------------------------------
+ free compress memory
+ -----------------------------------------------------------------------*/
+static void SyroVolcaSample_FreeCompressMemory(SyroManage *psm)
+{
+ int i;
+ SyroManageSingle *psms;
+
+ psms = (SyroManageSingle *)(psm+1);
+
+ for (i=0; i<psm->NumOfData; i++) {
+ if (psms->comp_buf) {
+ free(psms->comp_buf);
+ psms->comp_buf = NULL;
+ }
+ psms++;
+ }
+}
+
+/************************************************************************
+ Exteral Functions
+ ***********************************************************************/
+/*======================================================================
+ Syro Start
+ ======================================================================*/
+SyroStatus SyroVolcaSample_Start(SyroHandle *pHandle, SyroData *pData, int NumOfData,
+ uint32_t Flags, uint32_t *pNumOfSyroFrame)
+{
+ int i;
+ uint32_t handle_size;
+ uint32_t frame_size;
+ uint32_t comp_org_size, comp_dest_size, comp_ofs;
+ uint8_t *comp_src_adr;
+ Endian comp_endian;
+ SyroManage *psm;
+ SyroManageSingle *psms;
+
+ //--------------------------------
+ //------- Parameter check --------
+ //--------------------------------
+ if ((!NumOfData) || (NumOfData >= NUM_OF_DATA_MAX)) {
+ return Status_IllegalParameter;
+ }
+
+ frame_size = 0;
+
+ for (i=0; i<NumOfData; i++) {
+ switch (pData[i].DataType) {
+ case DataType_Sample_All:
+ if (pData[i].Size < ALL_INFO_SIZE) {
+ return Status_IllegalData;
+ }
+ frame_size += SyroVolcaSample_GetFrameSize_All(pData[i].Size);
+ break;
+
+ case DataType_Sample_AllCompress:
+ if (pData[i].Size < ALL_INFO_SIZE) {
+ return Status_IllegalData;
+ }
+ if ((pData[i].Quality < 8) || (pData[i].Quality > 16)) {
+ return Status_OutOfRange_Quality;
+ }
+ frame_size += SyroVolcaSample_GetFrameSize_AllComp(&pData[i]);
+ break;
+
+ case DataType_Pattern:
+ if (pData[i].Number >= VOLCASAMPLE_NUM_OF_PATTERN) {
+ return Status_OutOfRange_Number;
+ }
+ frame_size += SyroVolcaSample_GetFrameSize_Pattern();
+ break;
+
+ case DataType_Sample_Compress:
+ if (pData[i].Number >= VOLCASAMPLE_NUM_OF_SAMPLE) {
+ return Status_OutOfRange_Number;
+ }
+ if ((pData[i].Quality < 8) || (pData[i].Quality > 16)) {
+ return Status_OutOfRange_Quality;
+ }
+ frame_size += SyroVolcaSample_GetFrameSize_Sample_Comp(&pData[i]);
+ break;
+
+ case DataType_Sample_Erase:
+ if (pData[i].Number >= VOLCASAMPLE_NUM_OF_SAMPLE) {
+ return Status_OutOfRange_Number;
+ }
+ frame_size += SyroVolcaSample_GetFrameSize_Sample(0);
+ break;
+
+ case DataType_Sample_Liner:
+ if (pData[i].Number >= VOLCASAMPLE_NUM_OF_SAMPLE) {
+ return Status_OutOfRange_Number;
+ }
+ frame_size += SyroVolcaSample_GetFrameSize_Sample(pData[i].Size);
+ break;
+
+ default:
+ return Status_IllegalDataType;
+
+ }
+ }
+ frame_size += NUM_OF_FRAME__GAP_FOOTER;
+
+ //-----------------------------
+ //------- Alloc Memory --------
+ //-----------------------------
+
+ handle_size = sizeof(SyroManage) + (sizeof(SyroManageSingle) * NumOfData);
+ psm = (SyroManage *)malloc(handle_size);
+ if (!psm) {
+ return Status_NotEnoughMemory;
+ }
+ psms = (SyroManageSingle *)(psm+1);
+
+ //----------------------
+ //------- Setup --------
+ //----------------------
+
+ memset((uint8_t *)psm, 0, handle_size);
+ psm->Header = SYRO_MANAGE_HEADER;
+ psm->Flags = Flags;
+
+ psm->NumOfData = NumOfData;
+ for (i=0; i<NumOfData; i++) {
+ psms[i].Data = pData[i];
+
+ comp_org_size = 0;
+ comp_ofs = 0;
+ comp_src_adr = 0;
+ comp_endian = LittleEndian;
+
+ switch (pData[i].DataType) {
+ case DataType_Sample_Compress:
+ comp_src_adr = pData[i].pData;
+ comp_org_size = (pData[i].Size / 2);
+ comp_endian = pData[i].SampleEndian;
+ break;
+
+ case DataType_Sample_AllCompress:
+ if (psms[i].Data.Size == ALL_INFO_SIZE) {
+ psms[i].Data.DataType = DataType_Sample_All;
+ break;
+ }
+ comp_ofs = ALL_INFO_SIZE;
+ comp_src_adr = pData[i].pData + ALL_INFO_SIZE;
+ comp_org_size = ((pData[i].Size - ALL_INFO_SIZE) / 2);
+ comp_endian = LittleEndian;
+
+
+ default:
+ break;
+ }
+
+ if (comp_org_size) {
+ comp_dest_size = SyroComp_GetCompSize(
+ comp_src_adr,
+ comp_org_size,
+ pData[i].Quality,
+ comp_endian
+ );
+
+ comp_dest_size = (comp_dest_size + BLOCK_SIZE - 1) & (~(BLOCK_SIZE-1));
+ psms[i].comp_size = (comp_dest_size + comp_ofs);
+ psms[i].comp_buf = malloc(comp_dest_size + comp_ofs);
+ if (!psms[i].comp_buf) {
+ SyroVolcaSample_FreeCompressMemory(psm);
+ free((uint8_t *)psm);
+ return Status_NotEnoughMemory;
+ };
+ memset(psms[i].comp_buf, 0, comp_dest_size);
+ if (comp_ofs) {
+ memcpy(psms[i].comp_buf, pData[i].pData, comp_ofs);
+ }
+ SyroComp_Comp(comp_src_adr, (psms[i].comp_buf+comp_ofs), comp_org_size,
+ pData[i].Quality, comp_endian);
+ }
+ }
+
+ SyroVolcaSample_SetupNextData(psm);
+
+ for (i=0; i<KORGSYRO_NUM_OF_CYCLE; i++) {
+ SyroVolcaSample_CycleHandler(psm);
+ psm->CyclePos += KORGSYRO_QAM_CYCLE;
+ }
+ psm->CyclePos = 0;
+
+ *pHandle = (SyroHandle)psm;
+ *pNumOfSyroFrame = frame_size;
+
+ return Status_Success;
+}
+
+/*======================================================================
+ Syro Get Sample
+ ======================================================================*/
+SyroStatus SyroVolcaSample_GetSample(SyroHandle Handle, int16_t *pLeft, int16_t *pRight)
+{
+ SyroManage *psm;
+
+ psm = (SyroManage *)Handle;
+ if (psm->Header != SYRO_MANAGE_HEADER) {
+ return Status_InvalidHandle;
+ }
+
+ if (!psm->FrameCountInCycle) {
+ return Status_NoData;
+ }
+
+ *pLeft = SyroVolcaSample_GetChSample(psm, 0);
+ *pRight = SyroVolcaSample_GetChSample(psm, 1);
+
+ psm->FrameCountInCycle--;
+ if ((++psm->CyclePos) == KORGSYRO_NUM_OF_CYCLE_BUF) {
+ psm->CyclePos = 0;
+ }
+
+ if (!(psm->CyclePos % KORGSYRO_QAM_CYCLE)) {
+ SyroVolcaSample_CycleHandler(psm);
+ }
+
+ return Status_Success;
+}
+
+/*======================================================================
+ Syro End
+ ======================================================================*/
+SyroStatus SyroVolcaSample_End(SyroHandle Handle)
+{
+ SyroManage *psm;
+
+ psm = (SyroManage *)Handle;
+ if (psm->Header != SYRO_MANAGE_HEADER) {
+ return Status_InvalidHandle;
+ }
+
+ SyroVolcaSample_FreeCompressMemory(psm);
+
+ free((uint8_t *)psm);
+
+ return Status_Success;
+}
+
--- /dev/null
+++ b/korg_syro_volcasample.h
@@ -1,0 +1,79 @@
+#ifndef KORG_SYRO_VOLCASAMPLE_H__
+#define KORG_SYRO_VOLCASAMPLE_H__
+
+#include "korg_syro_type.h"
+
+//////////////////////////////////////////////////////////////////
+// SYRO VERSION 1.00
+
+#define SYRO_VOLCASAMPLE_VERSION 0x100
+
+//////////////////////////////////////////////////////////////////
+#define VOLCASAMPLE_NUM_OF_SAMPLE 100
+#define VOLCASAMPLE_NUM_OF_PATTERN 10
+
+#define VOLCASAMPLE_PATTERN_SIZE 0xA40
+
+typedef enum {
+ Status_Success,
+
+ //------ Start -------
+ Status_IllegalDataType,
+ Status_IllegalData,
+ Status_IllegalParameter,
+ Status_OutOfRange_Number,
+ Status_OutOfRange_Quality,
+ Status_NotEnoughMemory,
+
+ //------ GetSample/End -------
+ Status_InvalidHandle,
+ Status_NoData
+} SyroStatus;
+
+typedef enum {
+ LittleEndian,
+ BigEndian
+} Endian;
+
+typedef enum {
+ DataType_Sample_Liner,
+ DataType_Sample_Compress,
+ DataType_Sample_Erase,
+ DataType_Sample_All,
+ DataType_Sample_AllCompress,
+ DataType_Pattern
+} SyroDataType;
+
+typedef struct {
+ SyroDataType DataType;
+ uint8_t *pData;
+ uint32_t Number; // Sample:0-99, Pattern:0-9
+ uint32_t Size; // Byte Size (if type=Sample)
+ uint32_t Quality; // specific Sample bit (8-16), if type=LossLess
+ uint32_t Fs;
+ Endian SampleEndian;
+} SyroData;
+
+typedef void* SyroHandle;
+
+/*-------------------------*/
+/*------ Functions --------*/
+/*-------------------------*/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+SyroStatus SyroVolcaSample_Start(SyroHandle *pHandle, SyroData *pData, int NumOfData,
+ uint32_t Flags, uint32_t *pNumOfSyroFrame);
+
+SyroStatus SyroVolcaSample_GetSample(SyroHandle Handle, int16_t *pLeft, int16_t *pRight);
+
+SyroStatus SyroVolcaSample_End(SyroHandle Handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // KORG_SYRO_H__
+
--- /dev/null
+++ b/volcasample_pattern.c
@@ -1,0 +1,71 @@
+/************************************************************************
+ volca sample pattern
+ ***********************************************************************/
+#include <string.h>
+#include "../syro/korg_syro_type.h"
+#include "volcasample_pattern.h"
+
+static const uint8_t ParamInitValue[VOLCASAMPLE_NUM_OF_PARAM] = {
+ 0x7f, // VOLCASAMPLE_PARAM_LEVEL
+ 0x40, // VOLCASAMPLE_PARAM_PAN
+ 0x40, // VOLCASAMPLE_PARAM_SPEED
+ 0x00, // VOLCASAMPLE_PARAM_AMPEG_ATTACK
+ 0x7F, // VOLCASAMPLE_PARAM_AMPEG_DECAY
+ 0x40, // VOLCASAMPLE_PARAM_PITCHEG_INT
+ 0x00, // VOLCASAMPLE_PARAM_PITCHEG_ATTACK
+ 0x7F, // VOLCASAMPLE_PARAM_PITCHEG_DECAY
+ 0x00, // VOLCASAMPLE_PARAM_START_POINT
+ 0x7f, // VOLCASAMPLE_PARAM_LENGTH
+ 0x7f // VOLCASAMPLE_PARAM_HICUT
+};
+
+/*----------------------------------------------------------------------------
+ Write 32Bit Value
+ ----------------------------------------------------------------------------*/
+static void set_32Bit_value(uint8_t *ptr, uint32_t dat)
+{
+ int i;
+
+ for (i=0; i<4; i++) {
+ *ptr++ = (uint8_t)dat;
+ dat >>= 8;
+ }
+}
+
+/*----------------------------------------------------------------------------
+ Write 16Bit Value
+ ----------------------------------------------------------------------------*/
+static void set_16Bit_value(uint8_t *ptr, uint16_t dat)
+{
+ int i;
+
+ for (i=0; i<2; i++) {
+ *ptr++ = (uint8_t)dat;
+ dat >>= 8;
+ }
+}
+
+/*=======================================================================
+ Init pattern data
+ =======================================================================*/
+void VolcaSample_Pattern_Init(VolcaSample_Pattern_Data *pattern_data)
+{
+ int part;
+
+ memset((uint8_t *)pattern_data, 0, sizeof(VolcaSample_Pattern_Data));
+
+ set_32Bit_value((uint8_t *)&pattern_data->Header, VOLCASAMPLE_PATTERN_HEADER);
+ set_16Bit_value((uint8_t *)&pattern_data->DevCode, VOLCASAMPLE_PATTERN_DEVCODE);
+
+ set_16Bit_value((uint8_t *)&pattern_data->ActiveStep, 0xffff);
+
+ for (part=0; part<VOLCASAMPLE_NUM_OF_PART; part++) {
+ pattern_data->Part[part].Level = 0x7f;
+ pattern_data->Part[part].FuncMemoryPart = VOLCASAMPLE_FUNC_MUTE;
+ memcpy(pattern_data->Part[part].Param, ParamInitValue, VOLCASAMPLE_NUM_OF_PARAM);
+ }
+
+ set_32Bit_value((uint8_t *)&pattern_data->Footer, VOLCASAMPLE_PATTERN_FOOTER);
+}
+
+
--- /dev/null
+++ b/volcasample_pattern.h
@@ -1,0 +1,120 @@
+#ifndef KORG_VOLCASAMPLE_PATTERN_H__
+#define KORG_VOLCASAMPLE_PATTERN_H__
+
+#include "korg_syro_type.h"
+
+/*--------------------------------*/
+/*--------- Pattern Data ---------*/
+/*--------------------------------*/
+
+#define VOLCASAMPLE_NUM_OF_PART 10
+#define VOLCASAMPLE_NUM_OF_STEP 16
+
+/*----- define bit of FuncMemoryPart ------*/
+#define VOLCASAMPLE_FUNC_BIT_NOTION 0
+#define VOLCASAMPLE_FUNC_BIT_LOOP 1
+#define VOLCASAMPLE_FUNC_BIT_REVERB 2
+#define VOLCASAMPLE_FUNC_BIT_REVERSE 3
+#define VOLCASAMPLE_FUNC_BIT_MUTE 4
+
+#define VOLCASAMPLE_FUNC_MOTION (1 << VOLCASAMPLE_FUNC_BIT_NOTION)
+#define VOLCASAMPLE_FUNC_LOOP (1 << VOLCASAMPLE_FUNC_BIT_LOOP)
+#define VOLCASAMPLE_FUNC_REVERB (1 << VOLCASAMPLE_FUNC_BIT_REVERB)
+#define VOLCASAMPLE_FUNC_REVERSE (1 << VOLCASAMPLE_FUNC_BIT_REVERSE)
+#define VOLCASAMPLE_FUNC_MUTE (1 << VOLCASAMPLE_FUNC_BIT_MUTE)
+
+/*---- Knob Parameter ID -----*/
+#define VOLCASAMPLE_PARAM_LEVEL 0
+#define VOLCASAMPLE_PARAM_PAN 1
+#define VOLCASAMPLE_PARAM_SPEED 2
+#define VOLCASAMPLE_PARAM_AMPEG_ATTACK 3
+#define VOLCASAMPLE_PARAM_AMPEG_DECAY 4
+#define VOLCASAMPLE_PARAM_PITCHEG_INT 5
+#define VOLCASAMPLE_PARAM_PITCHEG_ATTACK 6
+#define VOLCASAMPLE_PARAM_PITCHEG_DECAY 7
+#define VOLCASAMPLE_PARAM_START_POINT 8
+#define VOLCASAMPLE_PARAM_LENGTH 9
+#define VOLCASAMPLE_PARAM_HICUT 10
+#define VOLCASAMPLE_NUM_OF_PARAM 11
+
+/*---- Motion Parameter ID -----*/
+#define VOLCASAMPLE_MOTION_LEVEL_0 0
+#define VOLCASAMPLE_MOTION_LEVEL_1 1
+#define VOLCASAMPLE_MOTION_PAN_0 2
+#define VOLCASAMPLE_MOTION_PAN_1 3
+#define VOLCASAMPLE_MOTION_SPEED_0 4
+#define VOLCASAMPLE_MOTION_SPEED_1 5
+#define VOLCASAMPLE_MOTION_AMPEG_ATTACK 6
+#define VOLCASAMPLE_MOTION_AMPEG_DECAY 7
+#define VOLCASAMPLE_MOTION_PITCHEG_INT 8
+#define VOLCASAMPLE_MOTION_PITCHEG_ATTACK 9
+#define VOLCASAMPLE_MOTION_PITCHEG_DECAY 10
+#define VOLCASAMPLE_MOTION_START_POINT 11
+#define VOLCASAMPLE_MOTION_LENGTH 12
+#define VOLCASAMPLE_MOTION_HICUT 13
+#define VOLCASAMPLE_NUM_OF_MOTION 14
+
+#define VOLCASAMPLE_PATTERN_HEADER 0x54535450 // 'PTST'
+#define VOLCASAMPLE_PATTERN_FOOTER 0x44455450 // 'PTED'
+#define VOLCASAMPLE_PATTERN_DEVCODE 0x33b8
+
+/////////////////////////////////////////////
+// !! notice !!
+//
+// *Those structures must not be padded by a compiler.
+// The declaration for forbidding it may be necessity.
+// (for example, like #pragma pack(1) )
+//
+// *Uint16_t and uint32_t are must be little endian.
+//
+
+/*----- part data struct ------*/
+typedef struct {
+ uint16_t SampleNum; // Sample num, 0~99
+ uint16_t StepOn; // Step on/off (b0~15 = STEP1~16)
+ uint16_t Accent; // Accent on/off (b0~15 = STEP 1~16, not supported)
+ uint16_t Reserved; // Reserved
+
+ uint8_t Level; // Part level 0~127, reccomend to set 127(not supported)
+ uint8_t Param[VOLCASAMPLE_NUM_OF_PARAM];
+ uint8_t FuncMemoryPart; // setting (refer VOLCASAMPLE_FUNC_xxxx)
+ uint8_t Padding1[11];
+
+ uint8_t Motion[VOLCASAMPLE_NUM_OF_MOTION][VOLCASAMPLE_NUM_OF_STEP];
+} VolcaSample_Part_Data;
+
+/*----- pattern data struct ------*/
+typedef struct {
+ //----- +0x00 -----
+ uint32_t Header;
+ uint16_t DevCode;
+ uint8_t Reserved[2];
+
+ uint16_t ActiveStep; // Active step on/off (b0~15 = STEP 1~16)
+
+ uint8_t Padding1[0x16];
+
+ //----- +0x20 - +0xA1F ------
+ VolcaSample_Part_Data Part[VOLCASAMPLE_NUM_OF_PART];
+
+ //----- +0xA20 - +0xA3F ------
+
+ uint8_t Padding2[0x1c];
+ uint32_t Footer;
+} VolcaSample_Pattern_Data;
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void VolcaSample_Pattern_Init(VolcaSample_Pattern_Data *pattern_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef KORG_VOLCASAMPLE_PATTERN_H__
+
+