├── .gitignore ├── EasyVolcaSample.c ├── EasyVolcaSample.exe ├── LICENSE ├── Makefile ├── README.md ├── compile.bat ├── dirent.h ├── korg_syro_comp.c ├── korg_syro_comp.h ├── korg_syro_func.c ├── korg_syro_func.h ├── korg_syro_type.h ├── korg_syro_volcasample.c └── korg_syro_volcasample.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | -------------------------------------------------------------------------------- /EasyVolcaSample.c: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | EasyVolcaSample 3 | =============== 4 | 5 | Easy upload .wav files to Korg Volca Sample! 6 | 7 | author: Joseph Ernest (twitter: @JosephErnest) 8 | date: 2015 March 1st 9 | url: http://github.com/josephernest/EasyVolcaSample 10 | license: MIT license 11 | note: uses the Korg Volca SDK: http://github.com/korginc/volcasample 12 | 13 | ***********************************************************************/ 14 | 15 | #ifdef _MSC_VER 16 | #define _CRT_SECURE_NO_WARNINGS 17 | #endif 18 | 19 | #include 20 | #include 21 | #include 22 | #include "korg_syro_volcasample.h" 23 | #include "korg_syro_comp.h" 24 | #ifdef _WIN32 25 | #include "dirent.h" 26 | #else 27 | #include 28 | #endif 29 | 30 | 31 | static const uint8_t wav_header[] = { 32 | 'R' , 'I' , 'F', 'F', // 'RIFF' 33 | 0x00, 0x00, 0x00, 0x00, // Size (data size + 0x24) 34 | 'W', 'A', 'V', 'E', // 'WAVE' 35 | 'f', 'm', 't', ' ', // 'fmt ' 36 | 0x10, 0x00, 0x00, 0x00, // Fmt chunk size 37 | 0x01, 0x00, // encode(wav) 38 | 0x02, 0x00, // channel = 2 39 | 0x44, 0xAC, 0x00, 0x00, // Fs (44.1kHz) 40 | 0x10, 0xB1, 0x02, 0x00, // Bytes per sec (Fs * 4) 41 | 0x04, 0x00, // Block Align (2ch,16Bit -> 4) 42 | 0x10, 0x00, // 16Bit 43 | 'd', 'a', 't', 'a', // 'data' 44 | 0x00, 0x00, 0x00, 0x00 // data size(bytes) 45 | }; 46 | 47 | #define WAVFMT_POS_ENCODE 0x00 48 | #define WAVFMT_POS_CHANNEL 0x02 49 | #define WAVFMT_POS_FS 0x04 50 | #define WAVFMT_POS_BIT 0x0E 51 | 52 | #define WAV_POS_RIFF_SIZE 0x04 53 | #define WAV_POS_WAVEFMT 0x08 54 | #define WAV_POS_DATA_SIZE 0x28 55 | 56 | 57 | /*---------------------------------------------------------------------------- 58 | Write 32Bit Value 59 | ----------------------------------------------------------------------------*/ 60 | static void set_32Bit_value(uint8_t *ptr, uint32_t dat) 61 | { 62 | int i; 63 | 64 | for (i=0; i<4; i++) { 65 | *ptr++ = (uint8_t)dat; 66 | dat >>= 8; 67 | } 68 | } 69 | 70 | /*---------------------------------------------------------------------------- 71 | Read 32Bit Value 72 | ----------------------------------------------------------------------------*/ 73 | static uint32_t get_32Bit_value(uint8_t *ptr) 74 | { 75 | int i; 76 | uint32_t dat; 77 | 78 | dat = 0; 79 | 80 | for (i=0; i<4; i++) { 81 | dat <<= 8; 82 | dat |= (uint32_t)ptr[3-i]; 83 | } 84 | return dat; 85 | } 86 | 87 | /*---------------------------------------------------------------------------- 88 | Read 16Bit Value 89 | ----------------------------------------------------------------------------*/ 90 | static uint16_t get_16Bit_value(uint8_t *ptr) 91 | { 92 | uint16_t dat; 93 | 94 | dat = (uint16_t)ptr[1]; 95 | dat <<= 8; 96 | dat |= (uint16_t)ptr[0]; 97 | 98 | return dat; 99 | } 100 | 101 | /*---------------------------------------------------------------------------- 102 | Read File 103 | ----------------------------------------------------------------------------*/ 104 | static uint8_t *read_file(char *filename, uint32_t *psize) 105 | { 106 | FILE *fp; 107 | uint8_t *buf; 108 | uint32_t size; 109 | 110 | fp = fopen((const char *)filename, "rb"); 111 | if (!fp) { 112 | printf ("File not found: %s \n", filename); 113 | return NULL; 114 | } 115 | 116 | fseek(fp, 0, SEEK_END); 117 | size = ftell(fp); 118 | fseek(fp, 0, SEEK_SET); 119 | 120 | buf = malloc(size); 121 | if (!buf) { 122 | printf ("Not enough memory for read file.\n"); 123 | fclose(fp); 124 | return NULL; 125 | } 126 | 127 | if (fread(buf, 1, size, fp) < size) { 128 | printf ("File read error, %s \n", filename); 129 | fclose(fp); 130 | free(buf); 131 | return NULL; 132 | } 133 | 134 | fclose(fp); 135 | 136 | *psize = size; 137 | return buf; 138 | } 139 | 140 | /*---------------------------------------------------------------------------- 141 | Write File 142 | ----------------------------------------------------------------------------*/ 143 | static bool write_file(char *filename, uint8_t *buf, uint32_t size) 144 | { 145 | FILE *fp; 146 | 147 | fp = fopen(filename, "wb"); 148 | if (!fp) { 149 | printf ("File open error, %s \n", filename); 150 | return false; 151 | } 152 | 153 | if (fwrite(buf, 1, size, fp) < size) { 154 | printf ("File write error(perhaps disk space is not enough), %s \n", filename); 155 | fclose(fp); 156 | return false; 157 | } 158 | 159 | fclose(fp); 160 | 161 | return true; 162 | } 163 | 164 | /***************************************************************************** 165 | functions for analyze command line, load file 166 | *****************************************************************************/ 167 | 168 | /*---------------------------------------------------------------------------- 169 | setup & load file (sample) 170 | ----------------------------------------------------------------------------*/ 171 | static bool setup_file_sample(char *filename, SyroData *syro_data) 172 | { 173 | uint8_t *src; 174 | uint32_t wav_pos, size, chunk_size; 175 | uint32_t wav_fs; 176 | uint16_t num_of_ch, sample_byte; 177 | uint32_t num_of_frame; 178 | 179 | src = read_file(filename, &size); 180 | if (!src) { 181 | return false; 182 | } 183 | 184 | printf ("file = %s, ", filename); 185 | 186 | if (size <= sizeof(wav_header)) { 187 | printf ("wav file error, too small.\n"); 188 | free(src); 189 | return false; 190 | } 191 | 192 | //------- check header/fmt -------*/ 193 | if (memcmp(src, wav_header, 4)) { 194 | printf ("wav file error, 'RIFF' is not found.\n"); 195 | free(src); 196 | return false; 197 | } 198 | 199 | if (memcmp((src + WAV_POS_WAVEFMT), (wav_header + WAV_POS_WAVEFMT), 8)) { 200 | printf ("wav file error, 'WAVE' or 'fmt ' is not found.\n"); 201 | free(src); 202 | return false; 203 | } 204 | 205 | wav_pos = WAV_POS_WAVEFMT + 4; // 'fmt ' pos 206 | 207 | if (get_16Bit_value(src+wav_pos+8+WAVFMT_POS_ENCODE) != 1) { 208 | printf ("wav file error, encode must be '1'.\n"); 209 | free(src); 210 | return false; 211 | } 212 | 213 | num_of_ch = get_16Bit_value(src+wav_pos+8+WAVFMT_POS_CHANNEL); 214 | if ((num_of_ch != 1) && (num_of_ch != 2)) { 215 | printf ("wav file error, channel must be 1 or 2.\n"); 216 | free(src); 217 | return false; 218 | } 219 | 220 | { 221 | uint16_t num_of_bit; 222 | 223 | num_of_bit = get_16Bit_value(src+wav_pos+8+WAVFMT_POS_BIT); 224 | if ((num_of_bit != 16) && (num_of_bit != 24)) { 225 | printf ("wav file error, bit must be 16 or 24.\n"); 226 | free(src); 227 | return false; 228 | } 229 | 230 | sample_byte = (num_of_bit / 8); 231 | } 232 | wav_fs = get_32Bit_value(src+wav_pos+8+WAVFMT_POS_FS); 233 | 234 | //------- search 'data' -------*/ 235 | for (;;) { 236 | chunk_size = get_32Bit_value(src+wav_pos+4); 237 | if (!memcmp((src+wav_pos), "data", 4)) { 238 | break; 239 | } 240 | wav_pos += chunk_size + 8; 241 | if ((wav_pos+8) > size) { 242 | printf ("wav file error, 'data' chunk not found.\n"); 243 | free(src); 244 | return false; 245 | } 246 | } 247 | 248 | if ((wav_pos+chunk_size+8) > size) { 249 | printf ("wav file error, illegal 'data' chunk size.\n"); 250 | free(src); 251 | return false; 252 | } 253 | 254 | //------- setup -------*/ 255 | num_of_frame = chunk_size / (num_of_ch * sample_byte); 256 | chunk_size = (num_of_frame * 2); 257 | syro_data->pData = malloc(chunk_size); 258 | if (!syro_data->pData) { 259 | printf ("not enough memory to setup file. \n"); 260 | free(src); 261 | return false; 262 | } 263 | 264 | //------- convert to 1ch, 16Bit -------*/ 265 | { 266 | uint8_t *poss; 267 | int16_t *posd; 268 | int32_t dat, datf; 269 | uint16_t ch, sbyte; 270 | 271 | poss = (src + wav_pos + 8); 272 | posd = (int16_t *)syro_data->pData; 273 | 274 | for (;;) { 275 | datf = 0; 276 | for (ch=0; chSize = chunk_size; 294 | syro_data->Fs = wav_fs; 295 | syro_data->SampleEndian = LittleEndian; 296 | 297 | free(src); 298 | 299 | printf ("ok.\n"); 300 | 301 | return true; 302 | } 303 | 304 | /*---------------------------------------------------------------------------- 305 | setup & load file (all) 306 | ----------------------------------------------------------------------------*/ 307 | static bool setup_file_all(char *filename, SyroData *syro_data) 308 | { 309 | uint32_t size; 310 | 311 | syro_data->pData = read_file(filename, &size); 312 | if (!syro_data->pData) { 313 | return false; 314 | } 315 | 316 | syro_data->Size = size; 317 | 318 | printf ("ok.\n"); 319 | 320 | return true; 321 | } 322 | 323 | 324 | /*---------------------------------------------------------------------------- 325 | setup & load file (pattern) 326 | ----------------------------------------------------------------------------*/ 327 | static bool setup_file_pattern(char *filename, SyroData *syro_data) 328 | { 329 | uint32_t size; 330 | 331 | syro_data->pData = read_file(filename, &size); 332 | if (!syro_data->pData) { 333 | return false; 334 | } 335 | if (size != VOLCASAMPLE_PATTERN_SIZE) { 336 | printf (" size error\n"); 337 | free(syro_data->pData); 338 | syro_data->pData = NULL; 339 | return false; 340 | } 341 | 342 | syro_data->Size = size; 343 | 344 | printf ("ok.\n"); 345 | 346 | return true; 347 | } 348 | 349 | /*---------------------------------------------------------------------------- 350 | free data memory 351 | ----------------------------------------------------------------------------*/ 352 | static void free_syrodata(SyroData *syro_data, int num_of_data) 353 | { 354 | int i; 355 | 356 | for (i=0; ipData) { 358 | free(syro_data->pData); 359 | syro_data->pData = NULL; 360 | } 361 | syro_data++; 362 | } 363 | } 364 | 365 | 366 | /***************************************************************************** 367 | Main 368 | *****************************************************************************/ 369 | 370 | static int main2(int argc, char **argv) 371 | { 372 | SyroData syro_data[100]; 373 | SyroData *syro_data_ptr = syro_data; 374 | SyroStatus status; 375 | SyroHandle handle; 376 | uint8_t *buf_dest; 377 | uint32_t size_dest; 378 | uint32_t frame, write_pos; 379 | int16_t left, right; 380 | 381 | //----- Loop on all .wav files in the current folder beginning with a number : "000 my sample.wav", "001Snare.wav", ..., "098Kick.wav" 382 | int num_of_data = 0; 383 | int i; 384 | 385 | DIR *dir; 386 | struct dirent *ent; 387 | if ((dir = opendir (".")) != NULL) 388 | { 389 | while ((ent = readdir (dir)) != NULL) 390 | { 391 | if (sscanf(ent->d_name, "%d%*.wav", &i) == 1) 392 | { 393 | if ((i >= 0) && (i < 100)) 394 | { 395 | if (!setup_file_sample(ent->d_name, syro_data_ptr)) { continue; } 396 | syro_data_ptr->DataType = DataType_Sample_Liner; 397 | syro_data_ptr->Number = i; 398 | syro_data_ptr++; 399 | num_of_data++; 400 | } 401 | } 402 | } 403 | closedir (dir); 404 | } else { return 1; } 405 | 406 | if (!num_of_data) { 407 | printf ("No file to upload. \n"); 408 | return 1; 409 | } 410 | 411 | //----- Start ------ 412 | status = SyroVolcaSample_Start(&handle, syro_data, num_of_data, 0, &frame); 413 | if (status != Status_Success) { 414 | printf ("Start error, %d \n", status); 415 | free_syrodata(syro_data, num_of_data); 416 | return 1; 417 | } 418 | 419 | size_dest = (frame * 4) + sizeof(wav_header); 420 | 421 | buf_dest = malloc(size_dest); 422 | if (!buf_dest) { 423 | printf ("Not enough memory for write file.\n"); 424 | SyroVolcaSample_End(handle); 425 | free_syrodata(syro_data, num_of_data); 426 | return 1; 427 | } 428 | 429 | memcpy(buf_dest, wav_header, sizeof(wav_header)); 430 | set_32Bit_value((buf_dest + WAV_POS_RIFF_SIZE), ((frame * 4) + 0x24)); 431 | set_32Bit_value((buf_dest + WAV_POS_DATA_SIZE), (frame * 4)); 432 | 433 | //----- convert loop ------ 434 | write_pos = sizeof(wav_header); 435 | while (frame) { 436 | SyroVolcaSample_GetSample(handle, &left, &right); 437 | buf_dest[write_pos++] = (uint8_t)left; 438 | buf_dest[write_pos++] = (uint8_t)(left >> 8); 439 | buf_dest[write_pos++] = (uint8_t)right; 440 | buf_dest[write_pos++] = (uint8_t)(right >> 8); 441 | frame--; 442 | } 443 | SyroVolcaSample_End(handle); 444 | free_syrodata(syro_data, num_of_data); 445 | 446 | //----- write ------ 447 | 448 | if (write_file("out.wav", buf_dest, size_dest)) { 449 | printf ("Complete to convert.\n"); 450 | } 451 | free(buf_dest); 452 | 453 | return 0; 454 | } 455 | 456 | /*---------------------------------------------------------------------------- 457 | Main (Wrapper) 458 | ----------------------------------------------------------------------------*/ 459 | int main(int argc, char **argv) 460 | { 461 | int ret; 462 | 463 | ret = main2(argc, argv); 464 | 465 | return ret; 466 | } -------------------------------------------------------------------------------- /EasyVolcaSample.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/josephernest/EasyVolcaSample/6b76050287dc1a235f1a3adf51b76974bd621540/EasyVolcaSample.exe -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Joseph Ernest 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET = EasyVolcaSample 2 | LIBS = -lm 3 | CC = gcc 4 | CFLAGS = -g -Wall 5 | 6 | .PHONY: default all clean 7 | 8 | default: $(TARGET) 9 | all: default 10 | 11 | OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c)) 12 | HEADERS = $(wildcard *.h) 13 | 14 | %.o: %.c $(HEADERS) 15 | $(CC) $(CFLAGS) -c $< -o $@ 16 | 17 | .PRECIOUS: $(TARGET) $(OBJECTS) 18 | 19 | $(TARGET): $(OBJECTS) 20 | $(CC) $(OBJECTS) -Wall $(LIBS) -o $@ 21 | 22 | clean: 23 | -rm -f *.o 24 | -rm -f $(TARGET) 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EasyVolcaSample 2 | =============== 3 | 4 | EasyVolcaSample is a lightweight tool that allows to easily upload .wav files to the Korg Volca Sample. 5 | 6 | To use this tool, *the only file you need* is [EasyVolcaSample.exe](http://josephernest.github.io/EasyVolcaSample/EasyVolcaSample.exe). 7 | 8 | [![ScreenShot](http://gget.it/pkos73mo/3.jpg)](http://youtu.be/eI8OYor5xgQ) 9 | 10 | How to use it? 11 | ---- 12 | 13 | 1. Put all the .wav files you want to upload in a single folder, named like this : 21 Blah.wav, 037 MySnare.wav, ..., 099Noise.wav. 14 | The only condition is that the filename must begin with a number (which will be the *sample number* on the Korg Volca Sample). 15 | 16 | 2. Run [EasyVolcaSample.exe](http://josephernest.github.io/EasyVolcaSample/EasyVolcaSample.exe) in the same folder 17 | 18 | 3. Play the generated `out.wav` file like this: 19 | 20 | `Computer speaker/line out <--- mini-jack-cable ---> Korg Volca Sample Sync IN` 21 | 22 | 4. Wait a few seconds or minutes, it's done! 23 | 24 | About 25 | ---- 26 | Author : Joseph Ernest ([@JosephErnest](http:/twitter.com/JosephErnest)) 27 | 28 | Notes 29 | ---- 30 | This project uses the [Korg Volca SDK](http://github.com/korginc/volcasample). 31 | 32 | License 33 | ---- 34 | MIT license -------------------------------------------------------------------------------- /compile.bat: -------------------------------------------------------------------------------- 1 | REM COMPILE WITH VC++ 2010 EXPRESS 2 | 3 | call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 4 | cl.exe *.c /FeEasyVolcaSample.exe 5 | del *.obj 6 | pause -------------------------------------------------------------------------------- /dirent.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dirent.h - dirent API for Microsoft Visual Studio 3 | * 4 | * Copyright (C) 2006-2012 Toni Ronkko 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining 7 | * a copy of this software and associated documentation files (the 8 | * ``Software''), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, 10 | * distribute, sublicense, and/or sell copies of the Software, and to 11 | * permit persons to whom the Software is furnished to do so, subject to 12 | * the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included 15 | * in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * $Id: dirent.h,v 1.20 2014/03/19 17:52:23 tronkko Exp $ 26 | */ 27 | #ifndef DIRENT_H 28 | #define DIRENT_H 29 | 30 | /* 31 | * Define architecture flags so we don't need to include windows.h. 32 | * Avoiding windows.h makes it simpler to use windows sockets in conjunction 33 | * with dirent.h. 34 | */ 35 | #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) 36 | # define _X86_ 37 | #endif 38 | #if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64) 39 | #define _AMD64_ 40 | #endif 41 | 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | /* Indicates that d_type field is available in dirent structure */ 55 | #define _DIRENT_HAVE_D_TYPE 56 | 57 | /* Indicates that d_namlen field is available in dirent structure */ 58 | #define _DIRENT_HAVE_D_NAMLEN 59 | 60 | /* Entries missing from MSVC 6.0 */ 61 | #if !defined(FILE_ATTRIBUTE_DEVICE) 62 | # define FILE_ATTRIBUTE_DEVICE 0x40 63 | #endif 64 | 65 | /* File type and permission flags for stat() */ 66 | #if !defined(S_IFMT) 67 | # define S_IFMT _S_IFMT /* File type mask */ 68 | #endif 69 | #if !defined(S_IFDIR) 70 | # define S_IFDIR _S_IFDIR /* Directory */ 71 | #endif 72 | #if !defined(S_IFCHR) 73 | # define S_IFCHR _S_IFCHR /* Character device */ 74 | #endif 75 | #if !defined(S_IFFIFO) 76 | # define S_IFFIFO _S_IFFIFO /* Pipe */ 77 | #endif 78 | #if !defined(S_IFREG) 79 | # define S_IFREG _S_IFREG /* Regular file */ 80 | #endif 81 | #if !defined(S_IREAD) 82 | # define S_IREAD _S_IREAD /* Read permission */ 83 | #endif 84 | #if !defined(S_IWRITE) 85 | # define S_IWRITE _S_IWRITE /* Write permission */ 86 | #endif 87 | #if !defined(S_IEXEC) 88 | # define S_IEXEC _S_IEXEC /* Execute permission */ 89 | #endif 90 | #if !defined(S_IFIFO) 91 | # define S_IFIFO _S_IFIFO /* Pipe */ 92 | #endif 93 | #if !defined(S_IFBLK) 94 | # define S_IFBLK 0 /* Block device */ 95 | #endif 96 | #if !defined(S_IFLNK) 97 | # define S_IFLNK 0 /* Link */ 98 | #endif 99 | #if !defined(S_IFSOCK) 100 | # define S_IFSOCK 0 /* Socket */ 101 | #endif 102 | 103 | #if defined(_MSC_VER) 104 | # define S_IRUSR S_IREAD /* Read user */ 105 | # define S_IWUSR S_IWRITE /* Write user */ 106 | # define S_IXUSR 0 /* Execute user */ 107 | # define S_IRGRP 0 /* Read group */ 108 | # define S_IWGRP 0 /* Write group */ 109 | # define S_IXGRP 0 /* Execute group */ 110 | # define S_IROTH 0 /* Read others */ 111 | # define S_IWOTH 0 /* Write others */ 112 | # define S_IXOTH 0 /* Execute others */ 113 | #endif 114 | 115 | /* Maximum length of file name */ 116 | #if !defined(PATH_MAX) 117 | # define PATH_MAX MAX_PATH 118 | #endif 119 | #if !defined(FILENAME_MAX) 120 | # define FILENAME_MAX MAX_PATH 121 | #endif 122 | #if !defined(NAME_MAX) 123 | # define NAME_MAX FILENAME_MAX 124 | #endif 125 | 126 | /* File type flags for d_type */ 127 | #define DT_UNKNOWN 0 128 | #define DT_REG S_IFREG 129 | #define DT_DIR S_IFDIR 130 | #define DT_FIFO S_IFIFO 131 | #define DT_SOCK S_IFSOCK 132 | #define DT_CHR S_IFCHR 133 | #define DT_BLK S_IFBLK 134 | #define DT_LNK S_IFLNK 135 | 136 | /* Macros for converting between st_mode and d_type */ 137 | #define IFTODT(mode) ((mode) & S_IFMT) 138 | #define DTTOIF(type) (type) 139 | 140 | /* 141 | * File type macros. Note that block devices, sockets and links cannot be 142 | * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are 143 | * only defined for compatibility. These macros should always return false 144 | * on Windows. 145 | */ 146 | #define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) 147 | #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) 148 | #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) 149 | #define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) 150 | #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) 151 | #define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) 152 | #define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) 153 | 154 | /* Return the exact length of d_namlen without zero terminator */ 155 | #define _D_EXACT_NAMLEN(p) ((p)->d_namlen) 156 | 157 | /* Return number of bytes needed to store d_namlen */ 158 | #define _D_ALLOC_NAMLEN(p) (PATH_MAX) 159 | 160 | 161 | #ifdef __cplusplus 162 | extern "C" { 163 | #endif 164 | 165 | 166 | /* Wide-character version */ 167 | struct _wdirent { 168 | long d_ino; /* Always zero */ 169 | unsigned short d_reclen; /* Structure size */ 170 | size_t d_namlen; /* Length of name without \0 */ 171 | int d_type; /* File type */ 172 | wchar_t d_name[PATH_MAX]; /* File name */ 173 | }; 174 | typedef struct _wdirent _wdirent; 175 | 176 | struct _WDIR { 177 | struct _wdirent ent; /* Current directory entry */ 178 | WIN32_FIND_DATAW data; /* Private file data */ 179 | int cached; /* True if data is valid */ 180 | HANDLE handle; /* Win32 search handle */ 181 | wchar_t *patt; /* Initial directory name */ 182 | }; 183 | typedef struct _WDIR _WDIR; 184 | 185 | static _WDIR *_wopendir (const wchar_t *dirname); 186 | static struct _wdirent *_wreaddir (_WDIR *dirp); 187 | static int _wclosedir (_WDIR *dirp); 188 | static void _wrewinddir (_WDIR* dirp); 189 | 190 | 191 | /* For compatibility with Symbian */ 192 | #define wdirent _wdirent 193 | #define WDIR _WDIR 194 | #define wopendir _wopendir 195 | #define wreaddir _wreaddir 196 | #define wclosedir _wclosedir 197 | #define wrewinddir _wrewinddir 198 | 199 | 200 | /* Multi-byte character versions */ 201 | struct dirent { 202 | long d_ino; /* Always zero */ 203 | unsigned short d_reclen; /* Structure size */ 204 | size_t d_namlen; /* Length of name without \0 */ 205 | int d_type; /* File type */ 206 | char d_name[PATH_MAX]; /* File name */ 207 | }; 208 | typedef struct dirent dirent; 209 | 210 | struct DIR { 211 | struct dirent ent; 212 | struct _WDIR *wdirp; 213 | }; 214 | typedef struct DIR DIR; 215 | 216 | static DIR *opendir (const char *dirname); 217 | static struct dirent *readdir (DIR *dirp); 218 | static int closedir (DIR *dirp); 219 | static void rewinddir (DIR* dirp); 220 | 221 | 222 | /* Internal utility functions */ 223 | static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); 224 | static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); 225 | 226 | static int dirent_mbstowcs_s( 227 | size_t *pReturnValue, 228 | wchar_t *wcstr, 229 | size_t sizeInWords, 230 | const char *mbstr, 231 | size_t count); 232 | 233 | static int dirent_wcstombs_s( 234 | size_t *pReturnValue, 235 | char *mbstr, 236 | size_t sizeInBytes, 237 | const wchar_t *wcstr, 238 | size_t count); 239 | 240 | static void dirent_set_errno (int error); 241 | 242 | /* 243 | * Open directory stream DIRNAME for read and return a pointer to the 244 | * internal working area that is used to retrieve individual directory 245 | * entries. 246 | */ 247 | static _WDIR* 248 | _wopendir( 249 | const wchar_t *dirname) 250 | { 251 | _WDIR *dirp = NULL; 252 | int error; 253 | 254 | /* Must have directory name */ 255 | if (dirname == NULL || dirname[0] == '\0') { 256 | dirent_set_errno (ENOENT); 257 | return NULL; 258 | } 259 | 260 | /* Allocate new _WDIR structure */ 261 | dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); 262 | if (dirp != NULL) { 263 | DWORD n; 264 | 265 | /* Reset _WDIR structure */ 266 | dirp->handle = INVALID_HANDLE_VALUE; 267 | dirp->patt = NULL; 268 | dirp->cached = 0; 269 | 270 | /* Compute the length of full path plus zero terminator */ 271 | n = GetFullPathNameW (dirname, 0, NULL, NULL); 272 | 273 | /* Allocate room for absolute directory name and search pattern */ 274 | dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); 275 | if (dirp->patt) { 276 | 277 | /* 278 | * Convert relative directory name to an absolute one. This 279 | * allows rewinddir() to function correctly even when current 280 | * working directory is changed between opendir() and rewinddir(). 281 | */ 282 | n = GetFullPathNameW (dirname, n, dirp->patt, NULL); 283 | if (n > 0) { 284 | wchar_t *p; 285 | 286 | /* Append search pattern \* to the directory name */ 287 | p = dirp->patt + n; 288 | if (dirp->patt < p) { 289 | switch (p[-1]) { 290 | case '\\': 291 | case '/': 292 | case ':': 293 | /* Directory ends in path separator, e.g. c:\temp\ */ 294 | /*NOP*/; 295 | break; 296 | 297 | default: 298 | /* Directory name doesn't end in path separator */ 299 | *p++ = '\\'; 300 | } 301 | } 302 | *p++ = '*'; 303 | *p = '\0'; 304 | 305 | /* Open directory stream and retrieve the first entry */ 306 | if (dirent_first (dirp)) { 307 | /* Directory stream opened successfully */ 308 | error = 0; 309 | } else { 310 | /* Cannot retrieve first entry */ 311 | error = 1; 312 | dirent_set_errno (ENOENT); 313 | } 314 | 315 | } else { 316 | /* Cannot retrieve full path name */ 317 | dirent_set_errno (ENOENT); 318 | error = 1; 319 | } 320 | 321 | } else { 322 | /* Cannot allocate memory for search pattern */ 323 | error = 1; 324 | } 325 | 326 | } else { 327 | /* Cannot allocate _WDIR structure */ 328 | error = 1; 329 | } 330 | 331 | /* Clean up in case of error */ 332 | if (error && dirp) { 333 | _wclosedir (dirp); 334 | dirp = NULL; 335 | } 336 | 337 | return dirp; 338 | } 339 | 340 | /* 341 | * Read next directory entry. The directory entry is returned in dirent 342 | * structure in the d_name field. Individual directory entries returned by 343 | * this function include regular files, sub-directories, pseudo-directories 344 | * "." and ".." as well as volume labels, hidden files and system files. 345 | */ 346 | static struct _wdirent* 347 | _wreaddir( 348 | _WDIR *dirp) 349 | { 350 | WIN32_FIND_DATAW *datap; 351 | struct _wdirent *entp; 352 | 353 | /* Read next directory entry */ 354 | datap = dirent_next (dirp); 355 | if (datap) { 356 | size_t n; 357 | DWORD attr; 358 | 359 | /* Pointer to directory entry to return */ 360 | entp = &dirp->ent; 361 | 362 | /* 363 | * Copy file name as wide-character string. If the file name is too 364 | * long to fit in to the destination buffer, then truncate file name 365 | * to PATH_MAX characters and zero-terminate the buffer. 366 | */ 367 | n = 0; 368 | while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) { 369 | entp->d_name[n] = datap->cFileName[n]; 370 | n++; 371 | } 372 | dirp->ent.d_name[n] = 0; 373 | 374 | /* Length of file name excluding zero terminator */ 375 | entp->d_namlen = n; 376 | 377 | /* File type */ 378 | attr = datap->dwFileAttributes; 379 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { 380 | entp->d_type = DT_CHR; 381 | } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { 382 | entp->d_type = DT_DIR; 383 | } else { 384 | entp->d_type = DT_REG; 385 | } 386 | 387 | /* Reset dummy fields */ 388 | entp->d_ino = 0; 389 | entp->d_reclen = sizeof (struct _wdirent); 390 | 391 | } else { 392 | 393 | /* Last directory entry read */ 394 | entp = NULL; 395 | 396 | } 397 | 398 | return entp; 399 | } 400 | 401 | /* 402 | * Close directory stream opened by opendir() function. This invalidates the 403 | * DIR structure as well as any directory entry read previously by 404 | * _wreaddir(). 405 | */ 406 | static int 407 | _wclosedir( 408 | _WDIR *dirp) 409 | { 410 | int ok; 411 | if (dirp) { 412 | 413 | /* Release search handle */ 414 | if (dirp->handle != INVALID_HANDLE_VALUE) { 415 | FindClose (dirp->handle); 416 | dirp->handle = INVALID_HANDLE_VALUE; 417 | } 418 | 419 | /* Release search pattern */ 420 | if (dirp->patt) { 421 | free (dirp->patt); 422 | dirp->patt = NULL; 423 | } 424 | 425 | /* Release directory structure */ 426 | free (dirp); 427 | ok = /*success*/0; 428 | 429 | } else { 430 | /* Invalid directory stream */ 431 | dirent_set_errno (EBADF); 432 | ok = /*failure*/-1; 433 | } 434 | return ok; 435 | } 436 | 437 | /* 438 | * Rewind directory stream such that _wreaddir() returns the very first 439 | * file name again. 440 | */ 441 | static void 442 | _wrewinddir( 443 | _WDIR* dirp) 444 | { 445 | if (dirp) { 446 | /* Release existing search handle */ 447 | if (dirp->handle != INVALID_HANDLE_VALUE) { 448 | FindClose (dirp->handle); 449 | } 450 | 451 | /* Open new search handle */ 452 | dirent_first (dirp); 453 | } 454 | } 455 | 456 | /* Get first directory entry (internal) */ 457 | static WIN32_FIND_DATAW* 458 | dirent_first( 459 | _WDIR *dirp) 460 | { 461 | WIN32_FIND_DATAW *datap; 462 | 463 | /* Open directory and retrieve the first entry */ 464 | dirp->handle = FindFirstFileW (dirp->patt, &dirp->data); 465 | if (dirp->handle != INVALID_HANDLE_VALUE) { 466 | 467 | /* a directory entry is now waiting in memory */ 468 | datap = &dirp->data; 469 | dirp->cached = 1; 470 | 471 | } else { 472 | 473 | /* Failed to re-open directory: no directory entry in memory */ 474 | dirp->cached = 0; 475 | datap = NULL; 476 | 477 | } 478 | return datap; 479 | } 480 | 481 | /* Get next directory entry (internal) */ 482 | static WIN32_FIND_DATAW* 483 | dirent_next( 484 | _WDIR *dirp) 485 | { 486 | WIN32_FIND_DATAW *p; 487 | 488 | /* Get next directory entry */ 489 | if (dirp->cached != 0) { 490 | 491 | /* A valid directory entry already in memory */ 492 | p = &dirp->data; 493 | dirp->cached = 0; 494 | 495 | } else if (dirp->handle != INVALID_HANDLE_VALUE) { 496 | 497 | /* Get the next directory entry from stream */ 498 | if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { 499 | /* Got a file */ 500 | p = &dirp->data; 501 | } else { 502 | /* The very last entry has been processed or an error occured */ 503 | FindClose (dirp->handle); 504 | dirp->handle = INVALID_HANDLE_VALUE; 505 | p = NULL; 506 | } 507 | 508 | } else { 509 | 510 | /* End of directory stream reached */ 511 | p = NULL; 512 | 513 | } 514 | 515 | return p; 516 | } 517 | 518 | /* 519 | * Open directory stream using plain old C-string. 520 | */ 521 | static DIR* 522 | opendir( 523 | const char *dirname) 524 | { 525 | struct DIR *dirp; 526 | int error; 527 | 528 | /* Must have directory name */ 529 | if (dirname == NULL || dirname[0] == '\0') { 530 | dirent_set_errno (ENOENT); 531 | return NULL; 532 | } 533 | 534 | /* Allocate memory for DIR structure */ 535 | dirp = (DIR*) malloc (sizeof (struct DIR)); 536 | if (dirp) { 537 | wchar_t wname[PATH_MAX]; 538 | size_t n; 539 | 540 | /* Convert directory name to wide-character string */ 541 | error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX); 542 | if (!error) { 543 | 544 | /* Open directory stream using wide-character name */ 545 | dirp->wdirp = _wopendir (wname); 546 | if (dirp->wdirp) { 547 | /* Directory stream opened */ 548 | error = 0; 549 | } else { 550 | /* Failed to open directory stream */ 551 | error = 1; 552 | } 553 | 554 | } else { 555 | /* 556 | * Cannot convert file name to wide-character string. This 557 | * occurs if the string contains invalid multi-byte sequences or 558 | * the output buffer is too small to contain the resulting 559 | * string. 560 | */ 561 | error = 1; 562 | } 563 | 564 | } else { 565 | /* Cannot allocate DIR structure */ 566 | error = 1; 567 | } 568 | 569 | /* Clean up in case of error */ 570 | if (error && dirp) { 571 | free (dirp); 572 | dirp = NULL; 573 | } 574 | 575 | return dirp; 576 | } 577 | 578 | /* 579 | * Read next directory entry. 580 | * 581 | * When working with text consoles, please note that file names returned by 582 | * readdir() are represented in the default ANSI code page while any output to 583 | * console is typically formatted on another code page. Thus, non-ASCII 584 | * characters in file names will not usually display correctly on console. The 585 | * problem can be fixed in two ways: (1) change the character set of console 586 | * to 1252 using chcp utility and use Lucida Console font, or (2) use 587 | * _cprintf function when writing to console. The _cprinf() will re-encode 588 | * ANSI strings to the console code page so many non-ASCII characters will 589 | * display correcly. 590 | */ 591 | static struct dirent* 592 | readdir( 593 | DIR *dirp) 594 | { 595 | WIN32_FIND_DATAW *datap; 596 | struct dirent *entp; 597 | 598 | /* Read next directory entry */ 599 | datap = dirent_next (dirp->wdirp); 600 | if (datap) { 601 | size_t n; 602 | int error; 603 | 604 | /* Attempt to convert file name to multi-byte string */ 605 | error = dirent_wcstombs_s( 606 | &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); 607 | 608 | /* 609 | * If the file name cannot be represented by a multi-byte string, 610 | * then attempt to use old 8+3 file name. This allows traditional 611 | * Unix-code to access some file names despite of unicode 612 | * characters, although file names may seem unfamiliar to the user. 613 | * 614 | * Be ware that the code below cannot come up with a short file 615 | * name unless the file system provides one. At least 616 | * VirtualBox shared folders fail to do this. 617 | */ 618 | if (error && datap->cAlternateFileName[0] != '\0') { 619 | error = dirent_wcstombs_s( 620 | &n, dirp->ent.d_name, PATH_MAX, 621 | datap->cAlternateFileName, PATH_MAX); 622 | } 623 | 624 | if (!error) { 625 | DWORD attr; 626 | 627 | /* Initialize directory entry for return */ 628 | entp = &dirp->ent; 629 | 630 | /* Length of file name excluding zero terminator */ 631 | entp->d_namlen = n - 1; 632 | 633 | /* File attributes */ 634 | attr = datap->dwFileAttributes; 635 | if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { 636 | entp->d_type = DT_CHR; 637 | } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { 638 | entp->d_type = DT_DIR; 639 | } else { 640 | entp->d_type = DT_REG; 641 | } 642 | 643 | /* Reset dummy fields */ 644 | entp->d_ino = 0; 645 | entp->d_reclen = sizeof (struct dirent); 646 | 647 | } else { 648 | /* 649 | * Cannot convert file name to multi-byte string so construct 650 | * an errornous directory entry and return that. Note that 651 | * we cannot return NULL as that would stop the processing 652 | * of directory entries completely. 653 | */ 654 | entp = &dirp->ent; 655 | entp->d_name[0] = '?'; 656 | entp->d_name[1] = '\0'; 657 | entp->d_namlen = 1; 658 | entp->d_type = DT_UNKNOWN; 659 | entp->d_ino = 0; 660 | entp->d_reclen = 0; 661 | } 662 | 663 | } else { 664 | /* No more directory entries */ 665 | entp = NULL; 666 | } 667 | 668 | return entp; 669 | } 670 | 671 | /* 672 | * Close directory stream. 673 | */ 674 | static int 675 | closedir( 676 | DIR *dirp) 677 | { 678 | int ok; 679 | if (dirp) { 680 | 681 | /* Close wide-character directory stream */ 682 | ok = _wclosedir (dirp->wdirp); 683 | dirp->wdirp = NULL; 684 | 685 | /* Release multi-byte character version */ 686 | free (dirp); 687 | 688 | } else { 689 | 690 | /* Invalid directory stream */ 691 | dirent_set_errno (EBADF); 692 | ok = /*failure*/-1; 693 | 694 | } 695 | return ok; 696 | } 697 | 698 | /* 699 | * Rewind directory stream to beginning. 700 | */ 701 | static void 702 | rewinddir( 703 | DIR* dirp) 704 | { 705 | /* Rewind wide-character string directory stream */ 706 | _wrewinddir (dirp->wdirp); 707 | } 708 | 709 | /* Convert multi-byte string to wide character string */ 710 | static int 711 | dirent_mbstowcs_s( 712 | size_t *pReturnValue, 713 | wchar_t *wcstr, 714 | size_t sizeInWords, 715 | const char *mbstr, 716 | size_t count) 717 | { 718 | int error; 719 | 720 | #if defined(_MSC_VER) && _MSC_VER >= 1400 721 | 722 | /* Microsoft Visual Studio 2005 or later */ 723 | error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); 724 | 725 | #else 726 | 727 | /* Older Visual Studio or non-Microsoft compiler */ 728 | size_t n; 729 | 730 | /* Convert to wide-character string (or count characters) */ 731 | n = mbstowcs (wcstr, mbstr, sizeInWords); 732 | if (!wcstr || n < count) { 733 | 734 | /* Zero-terminate output buffer */ 735 | if (wcstr && sizeInWords) { 736 | if (n >= sizeInWords) { 737 | n = sizeInWords - 1; 738 | } 739 | wcstr[n] = 0; 740 | } 741 | 742 | /* Length of resuting multi-byte string WITH zero terminator */ 743 | if (pReturnValue) { 744 | *pReturnValue = n + 1; 745 | } 746 | 747 | /* Success */ 748 | error = 0; 749 | 750 | } else { 751 | 752 | /* Could not convert string */ 753 | error = 1; 754 | 755 | } 756 | 757 | #endif 758 | 759 | return error; 760 | } 761 | 762 | /* Convert wide-character string to multi-byte string */ 763 | static int 764 | dirent_wcstombs_s( 765 | size_t *pReturnValue, 766 | char *mbstr, 767 | size_t sizeInBytes, /* max size of mbstr */ 768 | const wchar_t *wcstr, 769 | size_t count) 770 | { 771 | int error; 772 | 773 | #if defined(_MSC_VER) && _MSC_VER >= 1400 774 | 775 | /* Microsoft Visual Studio 2005 or later */ 776 | error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); 777 | 778 | #else 779 | 780 | /* Older Visual Studio or non-Microsoft compiler */ 781 | size_t n; 782 | 783 | /* Convert to multi-byte string (or count the number of bytes needed) */ 784 | n = wcstombs (mbstr, wcstr, sizeInBytes); 785 | if (!mbstr || n < count) { 786 | 787 | /* Zero-terminate output buffer */ 788 | if (mbstr && sizeInBytes) { 789 | if (n >= sizeInBytes) { 790 | n = sizeInBytes - 1; 791 | } 792 | mbstr[n] = '\0'; 793 | } 794 | 795 | /* Lenght of resulting multi-bytes string WITH zero-terminator */ 796 | if (pReturnValue) { 797 | *pReturnValue = n + 1; 798 | } 799 | 800 | /* Success */ 801 | error = 0; 802 | 803 | } else { 804 | 805 | /* Cannot convert string */ 806 | error = 1; 807 | 808 | } 809 | 810 | #endif 811 | 812 | return error; 813 | } 814 | 815 | /* Set errno variable */ 816 | static void 817 | dirent_set_errno( 818 | int error) 819 | { 820 | #if defined(_MSC_VER) && _MSC_VER >= 1400 821 | 822 | /* Microsoft Visual Studio 2005 and later */ 823 | _set_errno (error); 824 | 825 | #else 826 | 827 | /* Non-Microsoft compiler or older Microsoft compiler */ 828 | errno = error; 829 | 830 | #endif 831 | } 832 | 833 | 834 | #ifdef __cplusplus 835 | } 836 | #endif 837 | #endif /*DIRENT_H*/ 838 | 839 | -------------------------------------------------------------------------------- /korg_syro_comp.c: -------------------------------------------------------------------------------- 1 | 2 | /************************************************************************ 3 | SYRO for volca sample 4 | comprss PCM 5 | ***********************************************************************/ 6 | #include 7 | #include 8 | #include "korg_syro_type.h" 9 | #include "korg_syro_volcasample.h" 10 | #include "korg_syro_func.h" 11 | #include "korg_syro_comp.h" 12 | 13 | typedef struct { 14 | const uint8_t *ptr; 15 | uint32_t NumOfSample; 16 | int bitlen_eff; 17 | Endian SampleEndian; 18 | uint16_t sum; 19 | uint16_t padding; 20 | } ReadSample; 21 | 22 | typedef struct { 23 | uint8_t *ptr; 24 | int BitCount; 25 | int ByteCount; 26 | } WriteBit; 27 | 28 | 29 | /*----------------------------------------------------------------------------- 30 | Write Bit 31 | ** Update pwp member(ptr, BitCount, ByteCount) 32 | -----------------------------------------------------------------------------*/ 33 | static void SyroComp_WriteBit(WriteBit *pwp, uint32_t dat, int bit) 34 | { 35 | //-- write bit as big-endian format.(MSB->LSB) -- 36 | 37 | dat <<= (32-bit); 38 | dat >>= pwp->BitCount; 39 | 40 | for (;;) { 41 | if (pwp->BitCount) { 42 | *pwp->ptr |= (uint8_t)(dat>>24); 43 | } else { 44 | *pwp->ptr = (uint8_t)(dat>>24); 45 | } 46 | if ((pwp->BitCount + bit) >= 8) { 47 | bit -= (8 - pwp->BitCount); 48 | pwp->BitCount=0; 49 | pwp->ByteCount++; 50 | pwp->ptr++; 51 | dat <<= 8; 52 | } else { 53 | pwp->BitCount += bit; 54 | bit = 0; 55 | } 56 | if (!bit) { 57 | break; 58 | } 59 | } 60 | } 61 | 62 | /*----------------------------------------------------------------------------- 63 | Read PCM (fixed to 16bit) 64 | -----------------------------------------------------------------------------*/ 65 | static int32_t SyroComp_GetPcm(ReadSample *prp) 66 | { 67 | int32_t dat; 68 | 69 | if (prp->SampleEndian == LittleEndian) { 70 | dat = (int32_t)((int8_t)(prp->ptr[1])); 71 | dat <<= 8; 72 | dat |= (int32_t)(*prp->ptr); 73 | prp->ptr += 2; 74 | } else { 75 | dat = (int32_t)((int8_t)(*prp->ptr++)); 76 | dat <<= 8; 77 | dat |= (int32_t)(*prp->ptr++); 78 | } 79 | 80 | /*----- convert, 16Bit -> specified bit ----*/ 81 | if (prp->bitlen_eff < 16) { 82 | dat /= (1 << (16 - prp->bitlen_eff)); //replace from dat >>= (16 - prp->bitlen_eff); 83 | prp->sum += (uint16_t)(dat << (16 - prp->bitlen_eff)); 84 | } else { 85 | prp->sum += (uint16_t)dat; 86 | } 87 | 88 | return dat; 89 | } 90 | 91 | /*----------------------------------------------------------------------------- 92 | Generate bit-map, store to map_buffer 93 | -----------------------------------------------------------------------------*/ 94 | static void SyroComp_MakeMapBuffer(uint8_t *map_buffer, ReadSample *prp, int *pBitBase, int nBitBase, int type) 95 | { 96 | int i; 97 | uint32_t mcnt; 98 | int32_t dat[4]; 99 | int32_t datn; 100 | int bnum; 101 | 102 | memset(map_buffer, 0, VOLCASAMPLE_COMP_BLOCK_LEN); 103 | 104 | bnum = 0; 105 | mcnt = 0; 106 | map_buffer[mcnt++] = (uint8_t)prp->bitlen_eff; /* fix to full-bit 1st~3rd */ 107 | map_buffer[mcnt++] = (uint8_t)prp->bitlen_eff; 108 | map_buffer[mcnt++] = (uint8_t)prp->bitlen_eff; 109 | if (mcnt >= prp->NumOfSample) { 110 | return; 111 | } 112 | 113 | dat[3] = SyroComp_GetPcm(prp); 114 | dat[2] = SyroComp_GetPcm(prp); 115 | dat[1] = SyroComp_GetPcm(prp); 116 | for (;;) { 117 | dat[0] = SyroComp_GetPcm(prp); 118 | datn = dat[0]; 119 | if (type) { 120 | datn -= (dat[1]*2 - dat[2]); 121 | } 122 | if (datn < 0) { 123 | datn = -datn; 124 | } 125 | 126 | for (i=0; ibitlen_eff; 132 | } 133 | 134 | map_buffer[mcnt++] = (uint8_t)bnum; 135 | if (mcnt == prp->NumOfSample) { 136 | break; 137 | } 138 | dat[3] = dat[2]; 139 | dat[2] = dat[1]; 140 | dat[1] = dat[0]; 141 | } 142 | } 143 | 144 | /*----------------------------------------------------------------------------- 145 | convert bit-map in map_buffer. 146 | for example, bit=4,4,1,4 -> bit 4,4,4,4 147 | -----------------------------------------------------------------------------*/ 148 | static void SyroComp_MakeMap_BitConv(uint8_t *map_buffer, int num_of_sample, int bitlen) 149 | { 150 | int i, j; 151 | int dat, dat1; 152 | int datlo, dathi, datuse; 153 | int st; 154 | int pls, min; 155 | 156 | for (i=0; i i) { 176 | datuse = dathi; 177 | if (datlo > i) { 178 | datuse = datlo; 179 | } 180 | 181 | pls = (datuse-i) * (j-st); 182 | min = 2 + i; 183 | if (datuse==bitlen) { 184 | min++; 185 | } 186 | if (dathi==datlo) { 187 | min += 2 + datlo; 188 | if (datlo==bitlen) { 189 | min++; 190 | } 191 | } 192 | if (min>=pls) { 193 | for (; stbitlen_eff; 215 | datlim = -(1<<(bitlen-1)); 216 | 217 | dath[0] = 0; 218 | dath[1] = 0; 219 | dath[2] = 0; 220 | dath[3] = 0; 221 | 222 | prbit = map_buffer[0]; 223 | pr = 16 + 2; // 16=BitLen(4)*4, 2=1st Header 224 | 225 | for (i=0; i<(int)prp->NumOfSample; i++) { 226 | dath[0] = SyroComp_GetPcm(prp); 227 | bit = map_buffer[i]; 228 | if (bit != prbit) { 229 | pr += prbit; 230 | if (prbit==bitlen) { 231 | pr++; 232 | } 233 | pr += 2; 234 | prbit = bit; 235 | } 236 | pr += bit; 237 | if ((prbit < bitlen) && type) { 238 | dat = dath[0] - (dath[1]*2 - dath[2]); 239 | } else { 240 | dat = dath[0]; 241 | } 242 | if (bit==bitlen && dat==datlim) { 243 | pr++; 244 | } 245 | dath[3] = dath[2]; 246 | dath[2] = dath[1]; 247 | dath[1] = dath[0]; 248 | } 249 | pr += prbit; 250 | if (prbit==bitlen) { 251 | pr++; 252 | } 253 | 254 | return pr; 255 | } 256 | 257 | /*----------------------------------------------------------------------------- 258 | Make map (single type) 259 | (prp is updated) 260 | 261 | memo : comppcm.c-MakeMap2 262 | -----------------------------------------------------------------------------*/ 263 | static int SyroComp_MakeMap_SingleType(uint8_t *map_buffer, ReadSample *prp, int *pBitBase, int type) 264 | { 265 | ReadSample rp2; 266 | uint32_t len; 267 | uint32_t li; 268 | int i, j; 269 | int BitBase[16]; 270 | int bitlen; 271 | 272 | bitlen = prp->bitlen_eff; 273 | 274 | /*------- make map of all bit --------*/ 275 | 276 | for (i=0; i<(bitlen-1); i++) { 277 | BitBase[i] = i+1; 278 | } 279 | rp2 = *prp; 280 | SyroComp_MakeMapBuffer(map_buffer, &rp2, BitBase, (bitlen-1), type); 281 | SyroComp_MakeMap_BitConv(map_buffer, (int)rp2.NumOfSample, bitlen); 282 | 283 | /*------- Check maked map and guess bit -------*/ 284 | { 285 | int BitBaseScore[16]; 286 | int maxbit, maxsc, sc; 287 | 288 | for (i=0; i<16; i++) { 289 | BitBaseScore[i] = 0; 290 | } 291 | for (li=0; liNumOfSample; li++) { 292 | sc = map_buffer[li]; 293 | if (sc < 16) { 294 | BitBaseScore[sc]++; 295 | } 296 | } 297 | 298 | /*-- select top 4 depth -----*/ 299 | 300 | for (i=0; i<4; i++) { 301 | maxsc = -1; 302 | maxbit = -1; 303 | for (j=0; j maxsc) { 305 | maxsc = BitBaseScore[j]; 306 | maxbit = j; 307 | } 308 | } 309 | BitBase[i] = maxbit; 310 | BitBaseScore[maxbit] = -1; 311 | } 312 | 313 | /*-- sort selected bit (low->high) ----*/ 314 | 315 | for (i=0; i<3; i++) { 316 | for (j=0; j<3; j++) { 317 | if (BitBase[j] > BitBase[j+1]) { 318 | sc = BitBase[j]; 319 | BitBase[j] = BitBase[j+1]; 320 | BitBase[j+1] = sc; 321 | } 322 | } 323 | } 324 | } 325 | 326 | /*-----------------------------------*/ 327 | 328 | rp2 = *prp; 329 | SyroComp_MakeMapBuffer(map_buffer, &rp2, BitBase, 4, type); 330 | SyroComp_MakeMap_BitConv(map_buffer, (int)prp->NumOfSample, bitlen); 331 | 332 | rp2 = *prp; 333 | len = (uint32_t)SyroComp_GetCompSizeFromMap(map_buffer, &rp2, type); 334 | for (i=0; i<4; i++) { 335 | pBitBase[i] = BitBase[i]; 336 | } 337 | return (int)len; 338 | } 339 | 340 | 341 | /*----------------------------------------------------------------------------- 342 | make map, get size 343 | -- keep prp->ptr 344 | -----------------------------------------------------------------------------*/ 345 | static int SyroComp_MakeMap(uint8_t *map_buffer, ReadSample *prp, int *pBitBase, int *ptype) 346 | { 347 | int i; 348 | int besttype; 349 | int len, bestlen; 350 | int BitBase[4]; 351 | 352 | bestlen = 0; 353 | besttype = 0; 354 | 355 | for (i=0; i<2; i++) { 356 | len = SyroComp_MakeMap_SingleType(map_buffer, prp, BitBase, (i*2)); // type=0 or 2 357 | 358 | if ((!bestlen) || (len < bestlen)) { 359 | bestlen = len; 360 | besttype = i; 361 | } 362 | } 363 | 364 | if (pBitBase && ptype) { 365 | bestlen = SyroComp_MakeMap_SingleType(map_buffer, prp, pBitBase, (besttype*2)); 366 | *ptype = (besttype ? 2 : 0); 367 | } 368 | 369 | return bestlen; 370 | } 371 | 372 | /*----------------------------------------------------------------------------- 373 | Compress 1 block 374 | ** Update prp 375 | -----------------------------------------------------------------------------*/ 376 | static int SyroComp_CompBlock(uint8_t *map_buffer, uint8_t *dest, ReadSample *prp, int *pBitBase, int type) 377 | { 378 | int i, j, bit, prbit; 379 | int bitlen; 380 | int32_t dat, datlim; 381 | int32_t dath[4]; 382 | uint8_t hd; 383 | WriteBit wp; 384 | int BitHead[16]; 385 | 386 | wp.ptr = dest; 387 | wp.BitCount = 0; 388 | wp.ByteCount = 0; 389 | 390 | dath[0] = 0; 391 | dath[1] = 0; 392 | dath[2] = 0; 393 | dath[3] = 0; 394 | 395 | /*----- wrtie bit-base ------*/ 396 | j = 0; 397 | for (i=0; i<16; i++) { 398 | if (pBitBase[j]==i) { 399 | BitHead[i] = j++; 400 | SyroComp_WriteBit(&wp, (uint32_t)(i-1), 4); 401 | } else { 402 | BitHead[i] = -1; 403 | } 404 | } 405 | 406 | bitlen = prp->bitlen_eff; 407 | datlim = -(1<<(bitlen-1)); 408 | 409 | prbit = bitlen; 410 | SyroComp_WriteBit(&wp, 3, 2); 411 | 412 | for (i=0; i<(int)prp->NumOfSample; i++) { 413 | dath[0] = SyroComp_GetPcm(prp); 414 | bit = map_buffer[i]; 415 | if (bit != prbit) { 416 | /*--- write end mark ---*/ 417 | SyroComp_WriteBit(&wp, (1<<(prbit-1)), prbit); 418 | if (prbit==bitlen) { 419 | SyroComp_WriteBit(&wp, 1, 1); /* add 1 bit when full-bit */ 420 | } 421 | /*--- write this header ----*/ 422 | if (bit < bitlen) { 423 | hd = (uint8_t)BitHead[bit]; 424 | if (bit > prbit) { 425 | hd--; 426 | } 427 | } else { 428 | hd = 3; 429 | } 430 | SyroComp_WriteBit(&wp, hd, 2); 431 | prbit = bit; 432 | } 433 | if ((prbit < bitlen) && type) { 434 | dat = dath[0] - (dath[1]*2 - dath[2]); 435 | } else { 436 | dat = dath[0]; 437 | } 438 | SyroComp_WriteBit(&wp, (uint32_t)dat, prbit); 439 | if ((prbit == bitlen) && (dat == datlim)) { 440 | SyroComp_WriteBit(&wp, 0, 1); 441 | } 442 | dath[3] = dath[2]; 443 | dath[2] = dath[1]; 444 | dath[1] = dath[0]; 445 | } 446 | 447 | SyroComp_WriteBit(&wp, (1<<(prbit-1)), prbit); /* EndMark */ 448 | if (prbit == bitlen) { 449 | SyroComp_WriteBit(&wp, 1, 1); /* add 1 bit when full-bit */ 450 | } 451 | 452 | if (wp.BitCount) { 453 | SyroComp_WriteBit(&wp, 0, (8 - wp.BitCount)); 454 | } 455 | 456 | return wp.ByteCount; 457 | } 458 | 459 | 460 | /*====================================================================== 461 | Syro Get Sample 462 | ======================================================================*/ 463 | uint32_t SyroComp_GetCompSize(const uint8_t *psrc, uint32_t num_of_sample, 464 | uint32_t quality, Endian sample_endian) 465 | { 466 | ReadSample rp; 467 | uint32_t num_of_thissample; 468 | uint32_t allsize_byte; 469 | uint32_t thissize_bit; 470 | uint8_t *map_buffer; 471 | 472 | map_buffer = malloc(VOLCASAMPLE_COMP_BLOCK_LEN); 473 | if (!map_buffer) { 474 | return 0; 475 | } 476 | 477 | rp.ptr = psrc; 478 | rp.bitlen_eff = (int)quality; 479 | rp.SampleEndian = sample_endian; 480 | 481 | allsize_byte = 0; 482 | 483 | for (;;) { 484 | num_of_thissample = VOLCASAMPLE_COMP_BLOCK_LEN; 485 | if (num_of_thissample > num_of_sample) { 486 | num_of_thissample = num_of_sample; 487 | } 488 | rp.NumOfSample = num_of_thissample; 489 | thissize_bit = (uint32_t)SyroComp_MakeMap(map_buffer, &rp, NULL, NULL); 490 | 491 | if ((!thissize_bit) || (thissize_bit >= (quality * num_of_thissample))) { 492 | //----- use liner ---- 493 | thissize_bit = (quality * num_of_thissample); 494 | } 495 | allsize_byte += ((thissize_bit + 7) / 8); 496 | 497 | allsize_byte += 6; //--- for Header & CRC ----- 498 | 499 | rp.ptr += (num_of_thissample * 2); 500 | num_of_sample -= num_of_thissample; 501 | 502 | if (!num_of_sample) { 503 | break; 504 | } 505 | } 506 | 507 | free(map_buffer); 508 | 509 | return allsize_byte; 510 | } 511 | 512 | 513 | /*============================================================================= 514 | Compress Block 515 | psrc = pointer to source sample. 516 | pdest = pointer to store compressed data. 517 | num_of_sample = number of sample. 518 | quality = number of effective bit(8~16). 519 | sample_endian = specific endian of source sample(LittleEndian or BigEndian). 520 | =============================================================================*/ 521 | uint32_t SyroComp_Comp(const uint8_t *psrc, uint8_t *pdest, int num_of_sample, 522 | int quality, Endian sample_endian) 523 | { 524 | ReadSample rp; 525 | int BitBase[4]; 526 | int i; 527 | int srccount, count; 528 | int num_of_thissample; 529 | int prlen; 530 | int type; 531 | int32_t dat; 532 | uint8_t *map_buffer; 533 | 534 | map_buffer = malloc(VOLCASAMPLE_COMP_BLOCK_LEN); 535 | if (!map_buffer) { 536 | return 0; 537 | } 538 | 539 | rp.bitlen_eff = quality; 540 | rp.SampleEndian = sample_endian; 541 | rp.ptr = psrc; 542 | 543 | count = 0; 544 | srccount = 0; 545 | 546 | for (;;) { 547 | /*------- decide block length ------*/ 548 | num_of_thissample = VOLCASAMPLE_COMP_BLOCK_LEN; 549 | if (num_of_thissample > num_of_sample) { 550 | num_of_thissample = num_of_sample; 551 | } 552 | rp.NumOfSample = (uint32_t)num_of_thissample; 553 | rp.sum = 0; 554 | 555 | prlen = SyroComp_MakeMap(map_buffer, &rp, BitBase, &type); 556 | 557 | if (prlen && (prlen < (num_of_thissample*quality))) { 558 | /*----- compressible ------*/ 559 | *pdest++ = (uint8_t)(num_of_thissample>>8) | (uint8_t)(type<<5); 560 | *pdest++ = (uint8_t)num_of_thissample; 561 | prlen = SyroComp_CompBlock(map_buffer, pdest+4, &rp, BitBase, type); 562 | *pdest++ = (uint8_t)(prlen>>8); 563 | *pdest++ = (uint8_t)prlen; 564 | *pdest++ = (uint8_t)(rp.sum >> 8); 565 | *pdest++ = (uint8_t)rp.sum; 566 | count += (prlen+6); 567 | pdest += prlen; 568 | } else { 569 | /*----- copy without compression ------*/ 570 | *pdest++ = (uint8_t)(0xe0 | (num_of_thissample>>8)); 571 | *pdest++ = (uint8_t)num_of_thissample; 572 | *pdest++ = (uint8_t)(num_of_thissample>>7); 573 | *pdest++ = (uint8_t)(num_of_thissample<<1); 574 | { 575 | WriteBit wb; 576 | wb.ptr = (pdest+2); 577 | wb.BitCount = 0; 578 | wb.ByteCount = 0; 579 | 580 | for (i=0; i> 8); 588 | *pdest++ = (uint8_t)rp.sum; 589 | 590 | prlen = wb.ByteCount; 591 | pdest += prlen; 592 | count += (prlen+6); 593 | } 594 | } 595 | num_of_sample -= num_of_thissample; 596 | srccount += num_of_thissample; 597 | if (!num_of_sample) { 598 | break; 599 | } 600 | } 601 | 602 | free(map_buffer); 603 | 604 | return (uint32_t)count; 605 | } 606 | 607 | 608 | 609 | 610 | 611 | -------------------------------------------------------------------------------- /korg_syro_comp.h: -------------------------------------------------------------------------------- 1 | #ifndef KORG_SYRO_COMP_H__ 2 | #define KORG_SYRO_COMP_H__ 3 | 4 | #include "korg_syro_type.h" 5 | 6 | #define VOLCASAMPLE_COMP_BLOCK_LEN 0x800 7 | 8 | #ifdef __cplusplus 9 | extern "C" 10 | { 11 | #endif 12 | 13 | uint32_t SyroComp_GetCompSize(const uint8_t *psrc, uint32_t num_of_sample, 14 | uint32_t quality, Endian sample_endian); 15 | 16 | uint32_t SyroComp_Comp(const uint8_t *psrc, uint8_t *pdest, int num_of_sample, 17 | int quality, Endian sample_endian); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif 24 | 25 | -------------------------------------------------------------------------------- /korg_syro_func.c: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | KORG SYRO func 3 | ***********************************************************************/ 4 | #include 5 | #include 6 | #include "korg_syro_type.h" 7 | #include "korg_syro_func.h" 8 | 9 | static const uint8_t ecc_table[256] = { 10 | 0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00, 11 | 0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65, 12 | 0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66, 13 | 0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03, 14 | 0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69, 15 | 0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C, 16 | 0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F, 17 | 0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A, 18 | 0x6A,0x3F,0x3C,0x69,0x33,0x66,0x65,0x30,0x30,0x65,0x66,0x33,0x69,0x3C,0x3F,0x6A, 19 | 0x0F,0x5A,0x59,0x0C,0x56,0x03,0x00,0x55,0x55,0x00,0x03,0x56,0x0C,0x59,0x5A,0x0F, 20 | 0x0C,0x59,0x5A,0x0F,0x55,0x00,0x03,0x56,0x56,0x03,0x00,0x55,0x0F,0x5A,0x59,0x0C, 21 | 0x69,0x3C,0x3F,0x6A,0x30,0x65,0x66,0x33,0x33,0x66,0x65,0x30,0x6A,0x3F,0x3C,0x69, 22 | 0x03,0x56,0x55,0x00,0x5A,0x0F,0x0C,0x59,0x59,0x0C,0x0F,0x5A,0x00,0x55,0x56,0x03, 23 | 0x66,0x33,0x30,0x65,0x3F,0x6A,0x69,0x3C,0x3C,0x69,0x6A,0x3F,0x65,0x30,0x33,0x66, 24 | 0x65,0x30,0x33,0x66,0x3C,0x69,0x6A,0x3F,0x3F,0x6A,0x69,0x3C,0x66,0x33,0x30,0x65, 25 | 0x00,0x55,0x56,0x03,0x59,0x0C,0x0F,0x5A,0x5A,0x0F,0x0C,0x59,0x03,0x56,0x55,0x00 26 | }; 27 | 28 | static const uint16_t crc16_table[] = { 29 | 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 30 | 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 31 | 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 32 | 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 33 | 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 34 | 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 35 | 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 36 | 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 37 | 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 38 | 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 39 | 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 40 | 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 41 | 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 42 | 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 43 | 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 44 | 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 45 | 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 46 | 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 47 | 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 48 | 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 49 | 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 50 | 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 51 | 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 52 | 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 53 | 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 54 | 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 55 | 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 56 | 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 57 | 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 58 | 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 59 | 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 60 | 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 61 | }; 62 | 63 | static const int16_t sin_table[] = { 64 | 0, 23169, 32767, 23169, 0, -23169, -32767, -23169 65 | }; 66 | 67 | /*---------------------------------------------------------------- 68 | Calculate CRC16 69 | ----------------------------------------------------------------*/ 70 | uint16_t SyroFunc_CalculateCrc16(uint8_t *pSrc, int size) 71 | { 72 | int i; 73 | uint16_t dat, crc; 74 | 75 | crc = 0xffff; 76 | 77 | for (i=0; i> 8) ^ dat] ^ ((crc&0xff)<<8); 80 | } 81 | return crc; 82 | } 83 | 84 | /*---------------------------------------------------------------- 85 | Calculate ECC 86 | ----------------------------------------------------------------*/ 87 | uint32_t SyroFunc_CalculateEcc(uint8_t *pSrc, int size) 88 | { 89 | int i; 90 | uint8_t ecc_reg1, ecc_reg2, ecc_reg3; 91 | uint8_t ecc1, ecc2, bitpat_a, bitpat_b; 92 | uint8_t ci; 93 | uint32_t ecc; 94 | 95 | ecc_reg1 = 0; 96 | ecc_reg2 = 0; 97 | ecc_reg3 = 0; 98 | 99 | for (i=0; i>= 1; 118 | if (ecc_reg2 & bitpat_a) { 119 | ecc1 |= bitpat_b; 120 | } 121 | bitpat_b >>= 1; 122 | bitpat_a >>= 1; 123 | } 124 | 125 | bitpat_b = 0x80; 126 | for (i=0; i<4; i++) { 127 | if (ecc_reg3 & bitpat_a) { 128 | ecc2 |= bitpat_b; 129 | } 130 | bitpat_b >>= 1; 131 | if (ecc_reg2 & bitpat_a) { 132 | ecc2 |= bitpat_b; 133 | } 134 | bitpat_b >>= 1; 135 | bitpat_a >>= 1; 136 | } 137 | 138 | ecc_reg1 = (ecc_reg1 << 2) | 3; 139 | 140 | ecc = ecc_reg1; 141 | ecc <<= 8; 142 | ecc |= ecc2; 143 | ecc <<= 8; 144 | ecc |= ecc1; 145 | 146 | return ecc; 147 | } 148 | 149 | /*----------------------------------------------------------------------- 150 | Set Tx Size 151 | -----------------------------------------------------------------------*/ 152 | void SyroFunc_SetTxSize(uint8_t *ptr, uint32_t size, int num_of_bytes) 153 | { 154 | int i; 155 | 156 | for (i=0; i>= 8; 159 | } 160 | } 161 | 162 | /*---------------------------------------------------------------- 163 | Get sin value 164 | ----------------------------------------------------------------*/ 165 | static int16_t SyroFunc_GetSinValue(int phase, bool bData) 166 | { 167 | int32_t ret; 168 | 169 | ret = sin_table[phase]; 170 | 171 | if (bData) { 172 | if (ret > 0) { 173 | ret = 32767 - ret; 174 | ret = ((ret * ret) / 32767); 175 | ret = 32767 - ret; 176 | } else if (ret < 0) { 177 | ret += 32767; 178 | ret = ((ret * ret) / 32767); 179 | ret -= 32767; 180 | } 181 | } 182 | 183 | return (int16_t)ret; 184 | } 185 | 186 | /*----------------------------------------------------------------------- 187 | Generate Single Sycle 188 | -----------------------------------------------------------------------*/ 189 | void SyroFunc_GenerateSingleCycle(SyroChannel *psc, int write_page, uint8_t dat, bool block) 190 | { 191 | int i, phase_org, phase; 192 | int32_t dat1, dat2; 193 | int vol, dlt; 194 | int write_pos, write_pos_last; 195 | 196 | write_pos = write_page * KORGSYRO_QAM_CYCLE; 197 | write_pos_last = write_pos ? (write_pos - 1) : (KORGSYRO_NUM_OF_CYCLE_BUF - 1); 198 | 199 | phase_org = (dat >> 1) & 3; 200 | phase = phase_org * (KORGSYRO_QAM_CYCLE / 4); 201 | vol = (dat & 1); 202 | vol = vol ? 16 : 4; 203 | 204 | for (i=0; iLastPhase) { 209 | if (((psc->LastPhase & 1) && (phase_org & 1)) || 210 | (((psc->LastPhase + 1) & 3) == phase_org)) 211 | { 212 | dat2 = psc->CycleSample[write_pos_last]; 213 | dlt = dat1 - dat2; 214 | dlt /= 3; 215 | dat1 -= dlt; 216 | dat2 += dlt; 217 | psc->CycleSample[write_pos_last] = (int16_t)dat2; 218 | } 219 | } 220 | } 221 | 222 | psc->CycleSample[write_pos++] = (int16_t)dat1; 223 | if ((++phase) == KORGSYRO_QAM_CYCLE) { 224 | phase = 0; 225 | } 226 | } 227 | psc->LastPhase = phase_org; 228 | } 229 | 230 | /*----------------------------------------------------------------------- 231 | Smooth Start Mark 232 | -----------------------------------------------------------------------*/ 233 | static void SyroFunc_SmoothStartMark(SyroChannel *psc, int write_page) 234 | { 235 | int write_pos, write_pos_last; 236 | int32_t dat1, dat2, dat3, avg; 237 | 238 | write_pos = write_page * KORGSYRO_QAM_CYCLE; 239 | write_pos_last = write_pos ? (write_pos - 1) : (KORGSYRO_NUM_OF_CYCLE_BUF - 1); 240 | 241 | dat1 = psc->CycleSample[write_pos_last]; 242 | dat2 = psc->CycleSample[write_pos]; 243 | dat3 = psc->CycleSample[write_pos+1]; 244 | 245 | avg = (dat1 + dat2 + dat3) / 3; 246 | 247 | dat1 = (dat1 + avg) / 2; 248 | dat2 = (dat2 + avg) / 2; 249 | dat3 = (dat3 + avg) / 2; 250 | 251 | psc->CycleSample[write_pos_last] = (int16_t)dat1; 252 | psc->CycleSample[write_pos] = (int16_t)dat2; 253 | psc->CycleSample[write_pos+1] = (int16_t)dat3; 254 | } 255 | 256 | /*----------------------------------------------------------------------- 257 | Generate Gap 258 | -----------------------------------------------------------------------*/ 259 | void SyroFunc_MakeGap(SyroChannel *psc, int write_page) 260 | { 261 | uint8_t ch; 262 | 263 | for (ch=0; ch 7 | 8 | #else // #ifndef _MSC_VER 9 | 10 | #ifndef uint8_t 11 | typedef unsigned char uint8_t; 12 | #endif 13 | #ifndef int8_t 14 | typedef signed char int8_t; 15 | #endif 16 | 17 | #ifndef uint16_t 18 | typedef unsigned short uint16_t; 19 | #endif 20 | #ifndef int16_t 21 | typedef short int16_t; 22 | #endif 23 | 24 | #ifndef uint32_t 25 | typedef unsigned long uint32_t; 26 | #endif 27 | #ifndef int32_t 28 | typedef long int32_t; 29 | #endif 30 | 31 | #endif // #ifndef _MSC_VER 32 | 33 | #ifndef __cplusplus 34 | #ifndef bool 35 | typedef int bool; 36 | #endif 37 | #ifndef true 38 | #define true (1) 39 | #endif 40 | #ifndef false 41 | #define false (0) 42 | #endif 43 | #endif // #ifndef __cplusplus 44 | 45 | #endif // #ifndef KORG_SYRO_VOLCASAMPLE_H__ 46 | 47 | -------------------------------------------------------------------------------- /korg_syro_volcasample.c: -------------------------------------------------------------------------------- 1 | /************************************************************************ 2 | SYRO for volca sample 3 | ***********************************************************************/ 4 | #include 5 | #include 6 | #include "korg_syro_type.h" 7 | #include "korg_syro_volcasample.h" 8 | #include "korg_syro_func.h" 9 | #include "korg_syro_comp.h" 10 | 11 | #define NUM_OF_DATA_MAX (VOLCASAMPLE_NUM_OF_PATTERN + VOLCASAMPLE_NUM_OF_SAMPLE) 12 | #define VOLCA_SAMPLE_FS 31250 13 | #define SYRO_MANAGE_HEADER 0x47524F4B 14 | #define ALL_INFO_SIZE 0x4000 15 | 16 | #define BLOCK_SIZE 256 17 | #define BLOCK_PER_SECTOR 256 18 | #define BLOCK_PER_SUBSECTOR 16 19 | #define SUBSECTOR_SIZE (BLOCK_SIZE * BLOCK_PER_SUBSECTOR) 20 | 21 | #define LPF_FEEDBACK_LEVEL 0x2000 22 | 23 | #define NUM_OF_GAP_HEADER_CYCLE 10000 24 | #define NUM_OF_GAP_CYCLE 35 25 | #define NUM_OF_GAP_F_CYCLE 1000 26 | #define NUM_OF_GAP_FOOTER_CYCLE 3000 27 | #define NUM_OF_GAP_3S_CYCLE 15000 28 | 29 | #define NUM_OF_FRAME__GAP_HEADER (NUM_OF_GAP_HEADER_CYCLE * KORGSYRO_QAM_CYCLE) 30 | #define NUM_OF_FRAME__GAP (NUM_OF_GAP_CYCLE * KORGSYRO_QAM_CYCLE) 31 | #define NUM_OF_FRAME__GAP_F (NUM_OF_GAP_F_CYCLE * KORGSYRO_QAM_CYCLE) 32 | #define NUM_OF_FRAME__GAP_3S (NUM_OF_GAP_3S_CYCLE * KORGSYRO_QAM_CYCLE) 33 | #define NUM_OF_FRAME__GAP_FOOTER (NUM_OF_GAP_FOOTER_CYCLE * KORGSYRO_QAM_CYCLE) 34 | #define NUM_OF_FRAME__HEADER (49 * KORGSYRO_QAM_CYCLE) 35 | #define NUM_OF_FRAME__BLOCK (352 * KORGSYRO_QAM_CYCLE) 36 | 37 | #define TXHEADER_STR_LEN 16 38 | #define TXHEADER_STR "KORG SYSTEM FILE" 39 | #define TXHEADER_DEVICE_ID 0xff0033b8 // volca sample 40 | #define TXHEADER_BLOCK_ALL 0x01 41 | #define TXHEADER_BLOCK_ALL_COMPRESS 0x03 42 | #define TXHEADER_BLOCK_SAMPLE_LINER 0x10 43 | #define TXHEADER_BLOCK_PATTERN 0x20 44 | #define TXHEADER_BLOCK_SAMPLE_COMPRESS 0x30 45 | 46 | typedef enum { 47 | TaskStatus_Gap = 0, 48 | TaskStatus_StartMark, 49 | TaskStatus_ChannelInfo, 50 | TaskStatus_Data, 51 | TaskStatus_Gap_Footer, 52 | TaskStatus_End = -1 53 | } SyroTaskStatus; 54 | 55 | typedef struct { 56 | uint8_t Header[TXHEADER_STR_LEN]; 57 | uint32_t DeviceID; 58 | uint8_t BlockCode; 59 | uint8_t Num; 60 | 61 | uint8_t Misc[2]; 62 | uint8_t Size[4]; 63 | 64 | uint16_t m_Reserved; 65 | uint16_t m_Speed; 66 | } SyroTxHeader; 67 | 68 | typedef struct { 69 | uint32_t Header; 70 | uint32_t Flags; 71 | SyroTaskStatus TaskStatus; 72 | int TaskCount; 73 | 74 | //---- Manage source data(all) ----- 75 | int NumOfData; 76 | int CurData; 77 | 78 | //---- Manage source data(this) ----- 79 | const uint8_t *pSrcData; 80 | int DataCount; 81 | int DataSize; 82 | uint32_t EraseAlign; 83 | uint32_t EraseLength; 84 | uint32_t EraseCount; 85 | bool IsCompData; 86 | int CompBlockPos; 87 | uint32_t BlockLen1st; 88 | 89 | Endian SampleEndian; 90 | 91 | //---- Manage output data ----- 92 | uint8_t TxBlock[BLOCK_SIZE]; 93 | int TxBlockSize; 94 | int TxBlockPos; 95 | 96 | uint32_t PoolData; 97 | int PoolDataBit; 98 | 99 | bool UseEcc; 100 | uint32_t EccData; 101 | bool UseCrc; 102 | uint32_t CrcData; 103 | 104 | SyroChannel Channel[KORGSYRO_NUM_OF_CHANNEL]; 105 | int CyclePos; 106 | int FrameCountInCycle; 107 | 108 | int LongGapCount; // Debug Put 109 | } SyroManage; 110 | 111 | typedef struct { 112 | SyroData Data; 113 | uint8_t *comp_buf; 114 | uint32_t comp_size; 115 | } SyroManageSingle; 116 | 117 | /*----------------------------------------------------------------------- 118 | Setup Next Data 119 | -----------------------------------------------------------------------*/ 120 | static void SyroVolcaSample_SetupNextData(SyroManage *psm) 121 | { 122 | SyroManageSingle *psms; 123 | SyroTxHeader *psth; 124 | uint8_t block = 0; 125 | 126 | psms = (SyroManageSingle *)(psm+1); 127 | psms += psm->CurData; 128 | 129 | //----- Setup Tx Header ---- 130 | psth = (SyroTxHeader *)psm->TxBlock; 131 | 132 | memset((uint8_t *)psth, 0, sizeof(SyroTxHeader)); 133 | memcpy(psth->Header, TXHEADER_STR, TXHEADER_STR_LEN); 134 | psth->DeviceID = TXHEADER_DEVICE_ID; 135 | 136 | psth->Num = (uint8_t)psms->Data.Number; 137 | 138 | psm->SampleEndian = LittleEndian; 139 | psm->TxBlockSize = sizeof(SyroTxHeader); 140 | 141 | psm->pSrcData = psms->Data.pData; 142 | psm->DataSize = psms->Data.Size; 143 | psm->DataCount = 0; 144 | psm->IsCompData = false; 145 | psm->CompBlockPos = 0; 146 | psm->EraseAlign = 0; 147 | psm->EraseLength = 0; 148 | 149 | switch (psms->Data.DataType) { 150 | case DataType_Sample_All: 151 | case DataType_Sample_AllCompress: 152 | if (psms->Data.DataType == DataType_Sample_All) { 153 | block = TXHEADER_BLOCK_ALL; 154 | psth->Misc[0] = 0xff; 155 | } else { 156 | block = TXHEADER_BLOCK_ALL_COMPRESS; 157 | psm->pSrcData = psms->comp_buf; 158 | psm->DataSize = psms->comp_size; 159 | psm->IsCompData = true; 160 | psth->Misc[0] = (uint8_t)psms->Data.Quality; 161 | psm->BlockLen1st = ALL_INFO_SIZE; 162 | } 163 | if ((psm->CurData+1) < psm->NumOfData) { 164 | block++; //----- Set continue 165 | } 166 | 167 | SyroFunc_SetTxSize(psth->Size, psms->Data.Size, 4); 168 | psth->Misc[1] = 0xff; 169 | psth->Num = 0xff; 170 | psm->EraseAlign = (BLOCK_PER_SECTOR * BLOCK_SIZE); 171 | psm->EraseLength = NUM_OF_GAP_3S_CYCLE; 172 | psm->EraseCount = (psms->Data.Size + psm->EraseAlign - 1) / psm->EraseAlign; 173 | 174 | break; 175 | 176 | case DataType_Sample_Liner: 177 | case DataType_Sample_Compress: 178 | if (psms->Data.DataType == DataType_Sample_Liner) { 179 | block = TXHEADER_BLOCK_SAMPLE_LINER; 180 | } else { 181 | block = TXHEADER_BLOCK_SAMPLE_COMPRESS; 182 | psm->pSrcData = psms->comp_buf; 183 | psm->DataSize = psms->comp_size; 184 | psm->IsCompData = true; 185 | psth->Misc[0] = (uint8_t)psms->Data.Quality; 186 | psm->BlockLen1st = 0; 187 | } 188 | 189 | if ((psm->CurData+1) < psm->NumOfData) { 190 | block |= 1; //----- Set continue bit 191 | } 192 | SyroFunc_SetTxSize(psth->Size, psms->Data.Size, 4); 193 | 194 | psth->m_Reserved = 0xffff; 195 | psth->m_Speed = (uint16_t)(psms->Data.Fs * 0x4000 / VOLCA_SAMPLE_FS); 196 | 197 | psm->SampleEndian = psms->Data.SampleEndian; 198 | 199 | psm->EraseAlign = (SUBSECTOR_SIZE - 2); 200 | psm->EraseLength = NUM_OF_GAP_F_CYCLE; 201 | psm->EraseCount = (psms->Data.Size + psm->EraseAlign - 1) / psm->EraseAlign; 202 | 203 | break; 204 | 205 | case DataType_Sample_Erase: 206 | block = TXHEADER_BLOCK_SAMPLE_LINER; 207 | if ((psm->CurData+1) < psm->NumOfData) { 208 | block |= 1; //----- Set continue bit 209 | } 210 | psth->m_Reserved = 0xffff; 211 | psth->m_Speed = 0x4000; 212 | 213 | psm->pSrcData = NULL; 214 | psm->DataSize = 0; 215 | break; 216 | 217 | case DataType_Pattern: 218 | block = TXHEADER_BLOCK_PATTERN; 219 | if ((psm->CurData+1) < psm->NumOfData) { 220 | block |= 1; //----- Set continue bit 221 | } 222 | SyroFunc_SetTxSize(psth->Size, psm->DataSize, 4); 223 | 224 | break; 225 | 226 | default: 227 | break; 228 | } 229 | psth->BlockCode = block; 230 | 231 | psm->TaskStatus = TaskStatus_Gap; 232 | psm->TaskCount = NUM_OF_GAP_HEADER_CYCLE; 233 | } 234 | 235 | 236 | /*----------------------------------------------------------------------- 237 | Setup by TxBlock 238 | -----------------------------------------------------------------------*/ 239 | static void SyroVolcaSample_SetupBlock(SyroManage *psm) 240 | { 241 | bool use_ecc; 242 | 243 | use_ecc = (psm->TxBlockSize == BLOCK_SIZE) ? true : false; 244 | 245 | psm->TxBlockPos = 0; 246 | psm->TaskCount = psm->TxBlockSize; 247 | psm->UseEcc = use_ecc; 248 | psm->UseCrc = true; 249 | 250 | psm->CrcData = SyroFunc_CalculateCrc16(psm->TxBlock, psm->TxBlockSize); 251 | if (use_ecc) { 252 | psm->EccData = SyroFunc_CalculateEcc(psm->TxBlock, psm->TxBlockSize); 253 | } 254 | 255 | psm->PoolData = 0xa9; // Block Start Code 256 | psm->PoolDataBit = 8; 257 | } 258 | 259 | /************************************************************************ 260 | Internal Functions (Output Syro Data) 261 | ***********************************************************************/ 262 | /*----------------------------------------------------------------------- 263 | Generate Data 264 | ret : true if block is end. 265 | -----------------------------------------------------------------------*/ 266 | static bool SyroVolcaSample_MakeData(SyroManage *psm, int write_page) 267 | { 268 | int ch, bit; 269 | uint32_t dat; 270 | bool data_end; 271 | 272 | data_end = false; 273 | 274 | //------ Supply Data/Ecc/Crc ------ 275 | if (psm->PoolDataBit < (3 * KORGSYRO_NUM_OF_CHANNEL)) { 276 | if (psm->TaskCount) { 277 | dat = psm->TxBlock[psm->TxBlockPos++]; 278 | bit = 8; 279 | psm->TaskCount--; 280 | } else if (psm->UseEcc) { 281 | dat = psm->EccData; 282 | bit = 24; 283 | psm->UseEcc = false; 284 | } else if (psm->UseCrc) { 285 | dat = psm->CrcData; 286 | bit = 16; 287 | psm->UseCrc = false; 288 | } else { 289 | dat = 0; 290 | bit = (3 * KORGSYRO_NUM_OF_CHANNEL) - psm->PoolDataBit; 291 | data_end = true; 292 | } 293 | psm->PoolData |= (dat << psm->PoolDataBit); 294 | psm->PoolDataBit += bit; 295 | } 296 | 297 | //------ Make Cycle ------ 298 | for (ch=0; chChannel[ch], write_page, (psm->PoolData & 7), true); 300 | psm->PoolData >>= 3; 301 | psm->PoolDataBit -= 3; 302 | } 303 | 304 | return data_end; 305 | } 306 | 307 | /*----------------------------------------------------------------------- 308 | Nake Next Cycle 309 | -----------------------------------------------------------------------*/ 310 | static void SyroVolcaSample_CycleHandler(SyroManage *psm) 311 | { 312 | int write_page; 313 | uint32_t comp_len, org_len; 314 | 315 | write_page = (psm->CyclePos / KORGSYRO_QAM_CYCLE) ^ 1; 316 | 317 | switch (psm->TaskStatus) { 318 | case TaskStatus_Gap: 319 | SyroFunc_MakeGap(psm->Channel, write_page); 320 | if (!(--psm->TaskCount)) { 321 | psm->TaskStatus = TaskStatus_StartMark; 322 | SyroVolcaSample_SetupBlock(psm); 323 | } 324 | break; 325 | 326 | case TaskStatus_StartMark: 327 | SyroFunc_MakeStartMark(psm->Channel, write_page); 328 | psm->TaskStatus = TaskStatus_ChannelInfo; 329 | break; 330 | 331 | case TaskStatus_ChannelInfo: 332 | SyroFunc_MakeChannelInfo(psm->Channel, write_page); 333 | psm->TaskStatus = TaskStatus_Data; 334 | break; 335 | 336 | case TaskStatus_Data: 337 | if (SyroVolcaSample_MakeData(psm, write_page)) { 338 | if (psm->DataCount < psm->DataSize) { 339 | int pos, size; 340 | 341 | size = (psm->DataSize - psm->DataCount); 342 | if (size >= BLOCK_SIZE) { 343 | size = BLOCK_SIZE; 344 | } else { 345 | memset(psm->TxBlock, 0, BLOCK_SIZE); 346 | } 347 | if (psm->SampleEndian == LittleEndian) { 348 | memcpy(psm->TxBlock, (psm->pSrcData+psm->DataCount), size); 349 | } else { 350 | for (pos=0; posTxBlock[pos] = psm->pSrcData[psm->DataCount+pos+1]; 352 | psm->TxBlock[pos+1] = psm->pSrcData[psm->DataCount+pos]; 353 | } 354 | } 355 | psm->TaskStatus = TaskStatus_Gap; 356 | psm->TaskCount = NUM_OF_GAP_CYCLE; 357 | 358 | if (!psm->IsCompData) { 359 | if (psm->EraseAlign && (!(psm->DataCount % psm->EraseAlign))) { 360 | psm->TaskCount = psm->EraseLength; 361 | } 362 | } else { 363 | if (psm->EraseCount && (psm->CompBlockPos < (psm->DataCount+size))) { 364 | 365 | psm->TaskCount = psm->EraseLength; 366 | psm->EraseCount--; 367 | org_len = 0; 368 | 369 | for (;;) { 370 | if (psm->BlockLen1st) { 371 | psm->CompBlockPos += psm->BlockLen1st; 372 | org_len += psm->BlockLen1st; 373 | psm->BlockLen1st = 0; 374 | } else { 375 | comp_len = (uint32_t)psm->pSrcData[psm->CompBlockPos+2]; 376 | comp_len <<= 8; 377 | comp_len |= (uint32_t)psm->pSrcData[psm->CompBlockPos+3]; 378 | psm->CompBlockPos += (comp_len+6); 379 | org_len += (VOLCASAMPLE_COMP_BLOCK_LEN * 2); 380 | } 381 | if ((psm->CompBlockPos >= psm->DataSize) || 382 | (org_len >= psm->EraseAlign)) 383 | { 384 | break; 385 | } 386 | } 387 | } 388 | } 389 | 390 | psm->TxBlockSize = BLOCK_SIZE; 391 | psm->DataCount += size; 392 | 393 | } else { 394 | psm->CurData++; 395 | if (psm->CurData < psm->NumOfData) { 396 | SyroVolcaSample_SetupNextData(psm); 397 | } else { 398 | psm->TaskStatus = TaskStatus_Gap_Footer; 399 | psm->TaskCount = NUM_OF_GAP_FOOTER_CYCLE; 400 | } 401 | } 402 | } 403 | break; 404 | 405 | case TaskStatus_Gap_Footer: 406 | SyroFunc_MakeGap(psm->Channel, write_page); 407 | if (!(--psm->TaskCount)) { 408 | psm->TaskStatus = TaskStatus_End; 409 | } 410 | break; 411 | 412 | default: // case TaskStatus_End: 413 | return; 414 | } 415 | 416 | psm->FrameCountInCycle += KORGSYRO_QAM_CYCLE; 417 | } 418 | 419 | /*----------------------------------------------------------------------- 420 | Get Ch Sample 421 | -----------------------------------------------------------------------*/ 422 | static int16_t SyroVolcaSample_GetChSample(SyroManage *psm, int ch) 423 | { 424 | int32_t dat; 425 | 426 | dat = (int32_t)psm->Channel[ch].CycleSample[psm->CyclePos]; 427 | 428 | //----- LPF -----*/ 429 | dat = ((dat * (0x10000 - LPF_FEEDBACK_LEVEL)) + 430 | (psm->Channel[ch].Lpf_z * LPF_FEEDBACK_LEVEL)); 431 | dat /= 0x10000; 432 | psm->Channel[ch].Lpf_z = dat; 433 | 434 | return (int16_t)dat; 435 | } 436 | 437 | /*----------------------------------------------------------------------- 438 | Get Frame Size (union) 439 | -----------------------------------------------------------------------*/ 440 | static uint32_t SyroVolcaSample_GetFrameSize(int num_of_block) 441 | { 442 | uint32_t size; 443 | 444 | size = NUM_OF_FRAME__GAP_HEADER; 445 | size += NUM_OF_FRAME__HEADER; 446 | 447 | size += (NUM_OF_FRAME__GAP + NUM_OF_FRAME__BLOCK) * num_of_block; 448 | 449 | return size; 450 | } 451 | 452 | /*----------------------------------------------------------------------- 453 | Get Frame Size (Pattern) 454 | -----------------------------------------------------------------------*/ 455 | static uint32_t SyroVolcaSample_GetFrameSize_Pattern(void) 456 | { 457 | return SyroVolcaSample_GetFrameSize((VOLCASAMPLE_PATTERN_SIZE + BLOCK_SIZE - 1) / BLOCK_SIZE); 458 | } 459 | 460 | /*----------------------------------------------------------------------- 461 | Get Frame Size (Sample) 462 | -----------------------------------------------------------------------*/ 463 | static uint32_t SyroVolcaSample_GetFrameSize_Sample(uint32_t byte_size) 464 | { 465 | uint32_t size; 466 | uint32_t num_of_block; 467 | 468 | num_of_block = (byte_size + BLOCK_SIZE - 1) / BLOCK_SIZE; 469 | size = SyroVolcaSample_GetFrameSize(num_of_block); 470 | 471 | num_of_block = (byte_size + SUBSECTOR_SIZE - 3) / (SUBSECTOR_SIZE - 2); 472 | size += (NUM_OF_FRAME__GAP_F - NUM_OF_FRAME__GAP) * num_of_block; 473 | 474 | return size; 475 | } 476 | 477 | /*----------------------------------------------------------------------- 478 | Get Frame Size (Sample, Compress) 479 | -----------------------------------------------------------------------*/ 480 | static uint32_t SyroVolcaSample_GetFrameSize_Sample_Comp(SyroData *pdata) 481 | { 482 | uint32_t size, comp_size; 483 | uint32_t num_of_block; 484 | 485 | comp_size = SyroComp_GetCompSize( 486 | pdata->pData, 487 | (pdata->Size / 2), 488 | pdata->Quality, 489 | pdata->SampleEndian 490 | ); 491 | 492 | //----- get frame size from compressed size. 493 | num_of_block = (comp_size + BLOCK_SIZE - 1) / BLOCK_SIZE; 494 | size = SyroVolcaSample_GetFrameSize(num_of_block); 495 | 496 | //----- get gap size from original size. 497 | num_of_block = (pdata->Size + SUBSECTOR_SIZE - 3) / (SUBSECTOR_SIZE - 2); 498 | size += (NUM_OF_FRAME__GAP_F - NUM_OF_FRAME__GAP) * num_of_block; 499 | 500 | return size; 501 | } 502 | 503 | /*----------------------------------------------------------------------- 504 | Get Frame Size (All) 505 | -----------------------------------------------------------------------*/ 506 | static uint32_t SyroVolcaSample_GetFrameSize_All(uint32_t byte_size) 507 | { 508 | uint32_t size; 509 | uint32_t num_of_block; 510 | 511 | num_of_block = (byte_size + BLOCK_SIZE - 1) / BLOCK_SIZE; 512 | size = SyroVolcaSample_GetFrameSize(num_of_block); 513 | 514 | num_of_block = (num_of_block + BLOCK_PER_SECTOR - 1) / BLOCK_PER_SECTOR; 515 | size += (NUM_OF_FRAME__GAP_3S - NUM_OF_FRAME__GAP) * num_of_block; 516 | 517 | return size; 518 | } 519 | 520 | /*----------------------------------------------------------------------- 521 | Get Frame Size (All, Comp) 522 | -----------------------------------------------------------------------*/ 523 | static uint32_t SyroVolcaSample_GetFrameSize_AllComp(SyroData *pdata) 524 | { 525 | uint32_t size, comp_size; 526 | uint32_t num_of_block; 527 | 528 | if (pdata->Size == ALL_INFO_SIZE) { 529 | return SyroVolcaSample_GetFrameSize_All(pdata->Size); 530 | } 531 | 532 | comp_size = SyroComp_GetCompSize( 533 | (pdata->pData + ALL_INFO_SIZE), 534 | ((pdata->Size - ALL_INFO_SIZE) / 2), 535 | pdata->Quality, 536 | LittleEndian 537 | ); 538 | 539 | comp_size += ALL_INFO_SIZE; 540 | num_of_block = (comp_size + BLOCK_SIZE - 1) / BLOCK_SIZE; 541 | size = SyroVolcaSample_GetFrameSize(num_of_block); 542 | 543 | num_of_block = (pdata->Size + BLOCK_SIZE - 1) / BLOCK_SIZE; 544 | num_of_block = (num_of_block + BLOCK_PER_SECTOR - 1) / BLOCK_PER_SECTOR; 545 | size += (NUM_OF_FRAME__GAP_3S - NUM_OF_FRAME__GAP) * num_of_block; 546 | 547 | return size; 548 | } 549 | 550 | /*----------------------------------------------------------------------- 551 | free compress memory 552 | -----------------------------------------------------------------------*/ 553 | static void SyroVolcaSample_FreeCompressMemory(SyroManage *psm) 554 | { 555 | int i; 556 | SyroManageSingle *psms; 557 | 558 | psms = (SyroManageSingle *)(psm+1); 559 | 560 | for (i=0; iNumOfData; i++) { 561 | if (psms->comp_buf) { 562 | free(psms->comp_buf); 563 | psms->comp_buf = NULL; 564 | } 565 | psms++; 566 | } 567 | } 568 | 569 | /************************************************************************ 570 | Exteral Functions 571 | ***********************************************************************/ 572 | /*====================================================================== 573 | Syro Start 574 | ======================================================================*/ 575 | SyroStatus SyroVolcaSample_Start(SyroHandle *pHandle, SyroData *pData, int NumOfData, 576 | uint32_t Flags, uint32_t *pNumOfSyroFrame) 577 | { 578 | int i; 579 | uint32_t handle_size; 580 | uint32_t frame_size; 581 | uint32_t comp_org_size, comp_dest_size, comp_ofs; 582 | uint8_t *comp_src_adr; 583 | Endian comp_endian; 584 | SyroManage *psm; 585 | SyroManageSingle *psms; 586 | 587 | //-------------------------------- 588 | //------- Parameter check -------- 589 | //-------------------------------- 590 | if ((!NumOfData) || (NumOfData >= NUM_OF_DATA_MAX)) { 591 | return Status_IllegalParameter; 592 | } 593 | 594 | frame_size = 0; 595 | 596 | for (i=0; i 16)) { 610 | return Status_OutOfRange_Quality; 611 | } 612 | frame_size += SyroVolcaSample_GetFrameSize_AllComp(&pData[i]); 613 | break; 614 | 615 | case DataType_Pattern: 616 | if (pData[i].Number >= VOLCASAMPLE_NUM_OF_PATTERN) { 617 | return Status_OutOfRange_Number; 618 | } 619 | frame_size += SyroVolcaSample_GetFrameSize_Pattern(); 620 | break; 621 | 622 | case DataType_Sample_Compress: 623 | if (pData[i].Number >= VOLCASAMPLE_NUM_OF_SAMPLE) { 624 | return Status_OutOfRange_Number; 625 | } 626 | if ((pData[i].Quality < 8) || (pData[i].Quality > 16)) { 627 | return Status_OutOfRange_Quality; 628 | } 629 | frame_size += SyroVolcaSample_GetFrameSize_Sample_Comp(&pData[i]); 630 | break; 631 | 632 | case DataType_Sample_Erase: 633 | if (pData[i].Number >= VOLCASAMPLE_NUM_OF_SAMPLE) { 634 | return Status_OutOfRange_Number; 635 | } 636 | frame_size += SyroVolcaSample_GetFrameSize_Sample(0); 637 | break; 638 | 639 | case DataType_Sample_Liner: 640 | if (pData[i].Number >= VOLCASAMPLE_NUM_OF_SAMPLE) { 641 | return Status_OutOfRange_Number; 642 | } 643 | frame_size += SyroVolcaSample_GetFrameSize_Sample(pData[i].Size); 644 | break; 645 | 646 | default: 647 | return Status_IllegalDataType; 648 | 649 | } 650 | } 651 | frame_size += NUM_OF_FRAME__GAP_FOOTER; 652 | 653 | //----------------------------- 654 | //------- Alloc Memory -------- 655 | //----------------------------- 656 | 657 | handle_size = sizeof(SyroManage) + (sizeof(SyroManageSingle) * NumOfData); 658 | psm = (SyroManage *)malloc(handle_size); 659 | if (!psm) { 660 | return Status_NotEnoughMemory; 661 | } 662 | psms = (SyroManageSingle *)(psm+1); 663 | 664 | //---------------------- 665 | //------- Setup -------- 666 | //---------------------- 667 | 668 | memset((uint8_t *)psm, 0, handle_size); 669 | psm->Header = SYRO_MANAGE_HEADER; 670 | psm->Flags = Flags; 671 | 672 | psm->NumOfData = NumOfData; 673 | for (i=0; iCyclePos += KORGSYRO_QAM_CYCLE; 733 | } 734 | psm->CyclePos = 0; 735 | 736 | *pHandle = (SyroHandle)psm; 737 | *pNumOfSyroFrame = frame_size; 738 | 739 | return Status_Success; 740 | } 741 | 742 | /*====================================================================== 743 | Syro Get Sample 744 | ======================================================================*/ 745 | SyroStatus SyroVolcaSample_GetSample(SyroHandle Handle, int16_t *pLeft, int16_t *pRight) 746 | { 747 | SyroManage *psm; 748 | 749 | psm = (SyroManage *)Handle; 750 | if (psm->Header != SYRO_MANAGE_HEADER) { 751 | return Status_InvalidHandle; 752 | } 753 | 754 | if (!psm->FrameCountInCycle) { 755 | return Status_NoData; 756 | } 757 | 758 | *pLeft = SyroVolcaSample_GetChSample(psm, 0); 759 | *pRight = SyroVolcaSample_GetChSample(psm, 1); 760 | 761 | psm->FrameCountInCycle--; 762 | if ((++psm->CyclePos) == KORGSYRO_NUM_OF_CYCLE_BUF) { 763 | psm->CyclePos = 0; 764 | } 765 | 766 | if (!(psm->CyclePos % KORGSYRO_QAM_CYCLE)) { 767 | SyroVolcaSample_CycleHandler(psm); 768 | } 769 | 770 | return Status_Success; 771 | } 772 | 773 | /*====================================================================== 774 | Syro End 775 | ======================================================================*/ 776 | SyroStatus SyroVolcaSample_End(SyroHandle Handle) 777 | { 778 | SyroManage *psm; 779 | 780 | psm = (SyroManage *)Handle; 781 | if (psm->Header != SYRO_MANAGE_HEADER) { 782 | return Status_InvalidHandle; 783 | } 784 | 785 | SyroVolcaSample_FreeCompressMemory(psm); 786 | 787 | free((uint8_t *)psm); 788 | 789 | return Status_Success; 790 | } 791 | 792 | -------------------------------------------------------------------------------- /korg_syro_volcasample.h: -------------------------------------------------------------------------------- 1 | #ifndef KORG_SYRO_VOLCASAMPLE_H__ 2 | #define KORG_SYRO_VOLCASAMPLE_H__ 3 | 4 | #include "korg_syro_type.h" 5 | 6 | ////////////////////////////////////////////////////////////////// 7 | // SYRO VERSION 1.00 8 | 9 | #define SYRO_VOLCASAMPLE_VERSION 0x100 10 | 11 | ////////////////////////////////////////////////////////////////// 12 | #define VOLCASAMPLE_NUM_OF_SAMPLE 100 13 | #define VOLCASAMPLE_NUM_OF_PATTERN 10 14 | 15 | #define VOLCASAMPLE_PATTERN_SIZE 0xA40 16 | 17 | typedef enum { 18 | Status_Success, 19 | 20 | //------ Start ------- 21 | Status_IllegalDataType, 22 | Status_IllegalData, 23 | Status_IllegalParameter, 24 | Status_OutOfRange_Number, 25 | Status_OutOfRange_Quality, 26 | Status_NotEnoughMemory, 27 | 28 | //------ GetSample/End ------- 29 | Status_InvalidHandle, 30 | Status_NoData 31 | } SyroStatus; 32 | 33 | typedef enum { 34 | LittleEndian, 35 | BigEndian 36 | } Endian; 37 | 38 | typedef enum { 39 | DataType_Sample_Liner, 40 | DataType_Sample_Compress, 41 | DataType_Sample_Erase, 42 | DataType_Sample_All, 43 | DataType_Sample_AllCompress, 44 | DataType_Pattern 45 | } SyroDataType; 46 | 47 | typedef struct { 48 | SyroDataType DataType; 49 | uint8_t *pData; 50 | uint32_t Number; // Sample:0-99, Pattern:0-9 51 | uint32_t Size; // Byte Size (if type=Sample) 52 | uint32_t Quality; // specific Sample bit (8-16), if type=LossLess 53 | uint32_t Fs; 54 | Endian SampleEndian; 55 | } SyroData; 56 | 57 | typedef void* SyroHandle; 58 | 59 | /*-------------------------*/ 60 | /*------ Functions --------*/ 61 | /*-------------------------*/ 62 | #ifdef __cplusplus 63 | extern "C" 64 | { 65 | #endif 66 | 67 | SyroStatus SyroVolcaSample_Start(SyroHandle *pHandle, SyroData *pData, int NumOfData, 68 | uint32_t Flags, uint32_t *pNumOfSyroFrame); 69 | 70 | SyroStatus SyroVolcaSample_GetSample(SyroHandle Handle, int16_t *pLeft, int16_t *pRight); 71 | 72 | SyroStatus SyroVolcaSample_End(SyroHandle Handle); 73 | 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | #endif // KORG_SYRO_H__ 79 | 80 | --------------------------------------------------------------------------------