shithub: syro

Download patch

ref: b96d21bfc2516311ff6b5e6af3d6d0ae5ba0cae2
author: qwx <qwx@sciops.net>
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__
+
+