History

Big code change, read description

1) Don't calculate big LUTs for mixer deltas on init (was just a waste of RAM) 2) The mixer now uses a 64-bit division to calculate max number of safe samples to mix (branchless), instead of using a big hackish LUT for DIV->MUL 3) Module and sample loaders have been refactored so that it's much simpler to write new loaders (or modify the old ones) 4) Added support for importing DIGI Booster (non-Pro) modules 5) Added support for importing 8-channel StarTrekker modules 6) Updated help text 7) Some more minor code change 8) Updated the Visual Studio project and make scripts to include the new loaders * Sorry for not making individual commits for all the changes, but at this point it was simply too difficult for me to do so!

Olav Sørensen committed 5 years ago

Commit 12f28da1 parent 2c1dbb237 files · +6956 −6838Browse files

Showing the changes to src/ft2_sample_loader.c (1 of 37 files). Show all

Unified · Split

src/ft2_sample_loader.c+125−2071
@@ -16,1885 +16,124 @@ · 15 unmodified lines
16#include "ft2_diskop.h"16#include "ft2_diskop.h"
17#include "ft2_structs.h"17#include "ft2_structs.h"
18 18
19/* All of these routines were written from scratch and were not present19bool loadAIFF(FILE *f, uint32_t filesize);
20** in original FT2.20bool loadIFF(FILE *f, uint32_t filesize);
21*/21bool loadRAW(FILE *f, uint32_t filesize);
22bool loadWAV(FILE *f, uint32_t filesize);
22 23
23enum24enum
24{25{
25 STEREO_SAMPLE_READ_LEFT = 1,26 FORMAT_UNKNOWN = 0,
26 STEREO_SAMPLE_READ_RIGHT = 2,27 FORMAT_IFF = 1,
27 STEREO_SAMPLE_CONVERT = 3,28 FORMAT_WAV = 2,
28 29 FORMAT_AIFF = 3
29 WAV_FORMAT_PCM = 0x0001,30};
30 WAV_FORMAT_IEEE_FLOAT = 0x0003
31};
32
33static volatile bool sampleIsLoading;
34static bool loadAsInstrFlag;
35static uint8_t sampleSlot;
36static int16_t stereoSampleLoadMode;
37static SDL_Thread *thread;
38
39static void normalize32bitSigned(int32_t *sampleData, uint32_t sampleLength);
40static void normalize16bitFloatSigned(float *fSampleData, uint32_t sampleLength);
41static void normalize64bitDoubleSigned(double *dSampleData, uint32_t sampleLength);
42
43void freeTmpSample(sampleTyp *s)
44{
45 if (s->origPek != NULL)
46 {
47 free(s->origPek);
48 s->origPek = NULL;
49 s->pek = NULL;
50 }
51
52 memset(s, 0, sizeof (sampleTyp));
53}
54
55void removeSampleIsLoadingFlag(void)
56{
57 sampleIsLoading = false;
58}
59
60static int32_t getAIFFRate(uint8_t *in)
61{
62 int32_t exp = (int32_t)(((in[0] & 0x7F) << 8) | in[1]);
63 uint32_t lo = (in[2] << 24) | (in[3] << 16) | (in[4] << 8) | in[5];
64 uint32_t hi = (in[6] << 24) | (in[7] << 16) | (in[8] << 8) | in[9];
65
66 if (exp == 0 && lo == 0 && hi == 0)
67 return 0;
68
69 exp -= 16383;
70
71 double dOut = ldexp(lo, -31 + exp) + ldexp(hi, -63 + exp);
72 return (int32_t)(dOut + 0.5); // rounded
73}
74
75static bool aiffIsStereo(FILE *f) // only ran on files that are confirmed to be AIFFs
76{
77 uint16_t numChannels;
78 uint32_t chunkID, chunkSize;
79
80 uint32_t oldPos = ftell(f);
81
82 fseek(f, 0, SEEK_END);
83 int32_t filesize = ftell(f);
84
85 if (filesize < 12)
86 {
87 fseek(f, oldPos, SEEK_SET);
88 return false;
89 }
90
91 fseek(f, 12, SEEK_SET);
92
93 uint32_t commPtr = 0;
94 uint32_t commLen = 0;
95
96 int32_t bytesRead = 0;
97 while (!feof(f) && bytesRead < filesize-12)
98 {
99 fread(&chunkID, 4, 1, f); chunkID = SWAP32(chunkID); if (feof(f)) break;
100 fread(&chunkSize, 4, 1, f); chunkSize = SWAP32(chunkSize); if (feof(f)) break;
101
102 int32_t endOfChunk = (ftell(f) + chunkSize) + (chunkSize & 1);
103 switch (chunkID)
104 {
105 case 0x434F4D4D: // "COMM"
106 {
107 commPtr = ftell(f);
108 commLen = chunkSize;
109 }
110 break;
111
112 default: break;
113 }
114
115 bytesRead += (chunkSize + (chunkSize & 1));
116 fseek(f, endOfChunk, SEEK_SET);
117 }
118
119 if (commPtr == 0 || commLen < 2)
120 {
121 fseek(f, oldPos, SEEK_SET);
122 return false;
123 }
124
125 fseek(f, commPtr, SEEK_SET);
126 fread(&numChannels, 2, 1, f); numChannels = SWAP16(numChannels);
127 fseek(f, oldPos, SEEK_SET);
128
129 return (numChannels == 2);
130}
131
132static bool wavIsStereo(FILE *f) // only ran on files that are confirmed to be WAVs
133{
134 uint16_t numChannels;
135 uint32_t chunkID, chunkSize;
136
137 uint32_t oldPos = ftell(f);
138
139 fseek(f, 0, SEEK_END);
140 int32_t filesize = ftell(f);
141
142 if (filesize < 12)
143 {
144 fseek(f, oldPos, SEEK_SET);
145 return false;
146 }
147
148 fseek(f, 12, SEEK_SET);
149
150 uint32_t fmtPtr = 0;
151 uint32_t fmtLen = 0;
152
153 int32_t bytesRead = 0;
154 while (!feof(f) && bytesRead < filesize-12)
155 {
156 fread(&chunkID, 4, 1, f); if (feof(f)) break;
157 fread(&chunkSize, 4, 1, f); if (feof(f)) break;
158
159 int32_t endOfChunk = (ftell(f) + chunkSize) + (chunkSize & 1);
160 switch (chunkID)
161 {
162 case 0x20746D66: // "fmt "
163 {
164 fmtPtr = ftell(f);
165 fmtLen = chunkSize;
166 }
167 break;
168
169 default: break;
170 }
171
172 bytesRead += (chunkSize + (chunkSize & 1));
173 fseek(f, endOfChunk, SEEK_SET);
174 }
175
176 if (fmtPtr == 0 || fmtLen < 4)
177 {
178 fseek(f, oldPos, SEEK_SET);
179 return false;
180 }
181
182 fseek(f, fmtPtr + 2, SEEK_SET);
183 fread(&numChannels, 2, 1, f);
184 fseek(f, oldPos, SEEK_SET);
185
186 return (numChannels == 2);
187}
188
189static int32_t SDLCALL loadAIFFSample(void *ptr)
190{
191 char compType[4];
192 int8_t *audioDataS8;
193 uint8_t sampleRateBytes[10], *audioDataU8;
194 int16_t *audioDataS16, *audioDataS16_2, smp16;
195 uint16_t numChannels, bitDepth;
196 int32_t j, smp32, *audioDataS32;
197 uint32_t i, blockName, blockSize;
198 uint32_t offset, len32;
199 int64_t smp64;
200 sampleTyp tmpSmp;
201
202 // this is important for the "goto" on load error
203 FILE *f = NULL;
204 memset(&tmpSmp, 0, sizeof (tmpSmp));
205
206 if (editor.tmpFilenameU == NULL)
207 {
208 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
209 goto aiffLoadError;
210 }
211
212 UNICHAR *filename = editor.tmpFilenameU;
213
214 f = UNICHAR_FOPEN(filename, "rb");
215 if (f == NULL)
216 {
217 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
218 goto aiffLoadError;
219 }
220
221 fseek(f, 0, SEEK_END);
222 int32_t filesize = ftell(f);
223 if (filesize < 12)
224 {
225 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
226 goto aiffLoadError;
227 }
228
229 // handle chunks
230
231 uint32_t commPtr = 0;
232 uint32_t commLen = 0;
233 uint32_t ssndPtr = 0;
234 uint32_t ssndLen = 0;
235
236 fseek(f, 12, SEEK_SET);
237 while (!feof(f) && ftell(f) < filesize-12)
238 {
239 fread(&blockName, 4, 1, f); if (feof(f)) break;
240 fread(&blockSize, 4, 1, f); if (feof(f)) break;
241
242 blockName = SWAP32(blockName);
243 blockSize = SWAP32(blockSize);
244
245 switch (blockName)
246 {
247 case 0x434F4D4D: // "COMM"
248 {
249 commPtr = ftell(f);
250 commLen = blockSize;
251 }
252 break;
253
254 case 0x53534E44: // "SSND"
255 {
256 ssndPtr = ftell(f);
257 ssndLen = blockSize;
258 }
259 break;
260
261 default: break;
262 }
263
264 fseek(f, blockSize + (blockSize & 1), SEEK_CUR);
265 }
266
267 if (commPtr == 0 || commLen < 18 || ssndPtr == 0)
268 {
269 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
270 goto aiffLoadError;
271 }
272
273 // kludge for some really strange AIFFs
274 if (ssndLen == 0)
275 ssndLen = filesize - ssndPtr;
276
277 if (ssndPtr+ssndLen > (uint32_t)filesize)
278 ssndLen = filesize - ssndPtr;
279
280 fseek(f, commPtr, SEEK_SET);
281 fread(&numChannels, 2, 1, f); numChannels = SWAP16(numChannels);
282 fseek(f, 4, SEEK_CUR);
283 fread(&bitDepth, 2, 1, f); bitDepth = SWAP16(bitDepth);
284 fread(sampleRateBytes, 1, 10, f);
285
286 if (numChannels != 1 && numChannels != 2)
287 {
288 okBoxThreadSafe(0, "System message", "Error loading sample: Unsupported amounts of channels!");
289 goto aiffLoadError;
290 }
291
292 if (bitDepth != 8 && bitDepth != 16 && bitDepth != 24 && bitDepth != 32)
293 {
294 okBoxThreadSafe(0, "System message", "Error loading sample: Unsupported bitdepth!");
295 goto aiffLoadError;
296 }
297
298 // read compression type (if present)
299 if (commLen > 18)
300 {
301 fread(&compType, 1, 4, f);
302 if (memcmp(compType, "NONE", 4))
303 {
304 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
305 goto aiffLoadError;
306 }
307 }
308
309 uint32_t sampleRate = getAIFFRate(sampleRateBytes);
310
311 // sample data chunk
312
313 fseek(f, ssndPtr, SEEK_SET);
314
315 fread(&offset, 4, 1, f);
316 if (offset > 0)
317 {
318 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
319 goto aiffLoadError;
320 }
321
322 fseek(f, 4, SEEK_CUR);
323
324 ssndLen -= 8; // don't include offset and blockSize datas
325
326 uint32_t sampleLength = ssndLen;
327 if (sampleLength > MAX_SAMPLE_LEN)
328 sampleLength = MAX_SAMPLE_LEN;
329
330 freeTmpSample(&tmpSmp);
331
332 // read sample data
333
334 if (bitDepth == 8)
335 {
336 // 8-BIT SIGNED PCM
337
338 tmpSmp.origPek = (int8_t *)malloc(sampleLength + LOOP_FIX_LEN);
339 if (tmpSmp.origPek == NULL)
340 {
341 okBoxThreadSafe(0, "System message", "Not enough memory!");
342 goto aiffLoadError;
343 }
344
345 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
346
347 if (fread(tmpSmp.pek, sampleLength, 1, f) != 1)
348 {
349 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
350 goto aiffLoadError;
351 }
352
353 audioDataS8 = (int8_t *)tmpSmp.pek;
354
355 // stereo conversion
356 if (numChannels == 2)
357 {
358 sampleLength /= 2;
359
360 switch (stereoSampleLoadMode)
361 {
362 case STEREO_SAMPLE_READ_LEFT:
363 {
364 for (i = 1; i < sampleLength; i++)
365 audioDataS8[i] = audioDataS8[(i * 2) + 0];
366 }
367 break;
368
369 case STEREO_SAMPLE_READ_RIGHT:
370 {
371 len32 = sampleLength - 1;
372 for (i = 0; i < len32; i++)
373 audioDataS8[i] = audioDataS8[(i * 2) + 1];
374
375 audioDataS8[i] = 0;
376 }
377 break;
378
379 default:
380 case STEREO_SAMPLE_CONVERT:
381 {
382 len32 = sampleLength - 1;
383 for (i = 0; i < len32; i++)
384 {
385 smp16 = (audioDataS8[(i * 2) + 0] + audioDataS8[(i * 2) + 1]) >> 1;
386 audioDataS8[i] = (int8_t)smp16;
387 }
388
389 audioDataS8[i] = 0;
390 }
391 break;
392 }
393 }
394 }
395 else if (bitDepth == 16)
396 {
397 // 16-BIT SIGNED PCM
398
399 sampleLength /= 2;
400
401 tmpSmp.origPek = (int8_t *)malloc((sampleLength * 2) + LOOP_FIX_LEN);
402 if (tmpSmp.origPek == NULL)
403 {
404 okBoxThreadSafe(0, "System message", "Not enough memory!");
405 goto aiffLoadError;
406 }
407
408 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
409
410 if (fread(tmpSmp.pek, sampleLength, 2, f) != 2)
411 {
412 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
413 goto aiffLoadError;
414 }
415
416 // fix endianness
417 audioDataS16 = (int16_t *)tmpSmp.pek;
418 for (i = 0; i < sampleLength; i++)
419 audioDataS16[i] = SWAP16(audioDataS16[i]);
420
421 // stereo conversion
422 if (numChannels == 2)
423 {
424 sampleLength /= 2;
425
426 switch (stereoSampleLoadMode)
427 {
428 case STEREO_SAMPLE_READ_LEFT:
429 {
430 for (i = 1; i < sampleLength; i++)
431 audioDataS16[i] = audioDataS16[(i * 2) + 0];
432 }
433 break;
434
435 case STEREO_SAMPLE_READ_RIGHT:
436 {
437 len32 = sampleLength - 1;
438 for (i = 0; i < len32; i++)
439 audioDataS16[i] = audioDataS16[(i * 2) + 1];
440
441 audioDataS16[i] = 0;
442 }
443 break;
444
445 default:
446 case STEREO_SAMPLE_CONVERT:
447 {
448 len32 = sampleLength - 1;
449 for (i = 0; i < len32; i++)
450 {
451 smp32 = (audioDataS16[(i * 2) + 0] + audioDataS16[(i * 2) + 1]) >> 1;
452 audioDataS16[i] = (int16_t)smp32;
453 }
454
455 audioDataS16[i] = 0;
456 }
457 break;
458 }
459 }
460
461 sampleLength *= 2;
462 tmpSmp.typ |= 16;
463 }
464 else if (bitDepth == 24)
465 {
466 // 24-BIT SIGNED PCM
467
468 sampleLength /= 3;
469
470 tmpSmp.origPek = (int8_t *)malloc(((sampleLength * 4) * 2) + LOOP_FIX_LEN);
471 if (tmpSmp.origPek == NULL)
472 {
473 okBoxThreadSafe(0, "System message", "Not enough memory!");
474 goto aiffLoadError;
475 }
476
477 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
478
479 if (fread(&tmpSmp.pek[sampleLength], sampleLength, 3, f) != 3)
480 {
481 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
482 goto aiffLoadError;
483 }
484
485 audioDataS32 = (int32_t *)tmpSmp.pek;
486
487 // convert to 32-bit
488 audioDataU8 = (uint8_t *)tmpSmp.pek + sampleLength;
489 for (i = 0; i < sampleLength; i++)
490 {
491 audioDataS32[i] = (audioDataU8[0] << 24) | (audioDataU8[1] << 16) | (audioDataU8[2] << 8);
492 audioDataU8 += 3;
493 }
494
495 // stereo conversion
496 if (numChannels == 2)
497 {
498 sampleLength /= 2;
499
500 switch (stereoSampleLoadMode)
501 {
502 case STEREO_SAMPLE_READ_LEFT:
503 {
504 for (i = 1; i < sampleLength; i++)
505 audioDataS32[i] = audioDataS32[(i * 2) + 0];
506 }
507 break;
508
509 case STEREO_SAMPLE_READ_RIGHT:
510 {
511 len32 = sampleLength - 1;
512 for (i = 0; i < len32; i++)
513 audioDataS32[i] = audioDataS32[(i * 2) + 1];
514
515 audioDataS32[i] = 0;
516 }
517 break;
518
519 default:
520 case STEREO_SAMPLE_CONVERT:
521 {
522 len32 = sampleLength - 1;
523 for (i = 0; i < len32; i++)
524 {
525 smp64 = audioDataS32[(i * 2) + 0];
526 smp64 += audioDataS32[(i * 2) + 1];
527 smp64 >>= 1;
528
529 audioDataS32[i] = (int32_t)smp64;
530 }
531
532 audioDataS32[i] = 0;
533 }
534 break;
535 }
536 }
537
538 normalize32bitSigned(audioDataS32, sampleLength);
539
540 // downscale to 16-bit (ultra fast method!)
541
542 audioDataS16 = (int16_t *)tmpSmp.pek;
543 audioDataS16_2 = (int16_t *)tmpSmp.pek + 1;
544
545 for (i = 0; i < sampleLength; i++)
546 {
547 audioDataS16[i] = audioDataS16_2[i];
548 audioDataS16_2++;
549 }
550
551 sampleLength *= 2;
552 tmpSmp.typ |= 16;
553 }
554 else if (bitDepth == 32)
555 {
556 // 32-BIT SIGNED PCM
557
558 sampleLength /= 4;
559
560 tmpSmp.origPek = (int8_t *)malloc((sampleLength * 4) + LOOP_FIX_LEN);
561 if (tmpSmp.origPek == NULL)
562 {
563 okBoxThreadSafe(0, "System message", "Not enough memory!");
564 goto aiffLoadError;
565 }
566
567 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
568
569 if (fread(tmpSmp.pek, sampleLength, 4, f) != 4)
570 {
571 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
572 goto aiffLoadError;
573 }
574
575 // fix endianness
576 audioDataS32 = (int32_t *)tmpSmp.pek;
577 for (i = 0; i < sampleLength; i++)
578 audioDataS32[i] = SWAP32(audioDataS32[i]);
579
580 // stereo conversion
581 if (numChannels == 2)
582 {
583 sampleLength /= 2;
584
585 switch (stereoSampleLoadMode)
586 {
587 case STEREO_SAMPLE_READ_LEFT:
588 {
589 for (i = 1; i < sampleLength; i++)
590 audioDataS32[i] = audioDataS32[(i * 2) + 0];
591 }
592 break;
593
594 case STEREO_SAMPLE_READ_RIGHT:
595 {
596 len32 = sampleLength - 1;
597 for (i = 0; i < len32; i++)
598 audioDataS32[i] = audioDataS32[(i * 2) + 1];
599
600 audioDataS32[i] = 0;
601 }
602 break;
603
604 default:
605 case STEREO_SAMPLE_CONVERT:
606 {
607 len32 = sampleLength - 1;
608 for (i = 0; i < len32; i++)
609 {
610 smp64 = audioDataS32[(i * 2) + 0];
611 smp64 += audioDataS32[(i * 2) + 1];
612 smp64 >>= 1;
613
614 audioDataS32[i] = (int32_t)smp64;
615 }
616
617 audioDataS32[i] = 0;
618 }
619 break;
620 }
621 }
622
623 normalize32bitSigned(audioDataS32, sampleLength);
624
625 // downscale to 16-bit (ultra fast method!)
626
627 audioDataS16 = (int16_t *)tmpSmp.pek;
628 audioDataS16_2 = (int16_t *)tmpSmp.pek + 1;
629
630 for (i = 0; i < sampleLength; i++)
631 {
632 audioDataS16[i] = audioDataS16_2[i];
633 audioDataS16_2++;
634 }
635
636 sampleLength *= 2;
637 tmpSmp.typ |= 16;
638 }
639
640 // adjust memory needed
641 int8_t *newPtr = (int8_t *)realloc(tmpSmp.origPek, sampleLength + LOOP_FIX_LEN);
642 if (newPtr != NULL)
643 {
644 tmpSmp.origPek = newPtr;
645 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
646 }
647
648 // set sample attributes
649 tmpSmp.len = sampleLength;
650 tmpSmp.vol = 64;
651 tmpSmp.pan = 128;
652
653 tuneSample(&tmpSmp, sampleRate, audio.linearPeriodsFlag);
654
655 // set sample name
656 char *tmpFilename = unicharToCp437(filename, true);
657 if (tmpFilename != NULL)
658 {
659 j = (int32_t)strlen(tmpFilename);
660 while (j--)
661 {
662 if (tmpFilename[j] == DIR_DELIMITER)
663 break;
664 }
665
666 char *tmpPtr = tmpFilename;
667 if (j > 0)
668 tmpPtr += j + 1;
669
670 sanitizeFilename(tmpPtr);
671
672 uint32_t filenameLen = (uint32_t)strlen(tmpPtr);
673 for (i = 0; i < 22; i++)
674 {
675 if (i < filenameLen)
676 tmpSmp.name[i] = tmpPtr[i];
677 else
678 tmpSmp.name[i] = '\0';
679 }
680
681 free(tmpFilename);
682 }
683
684 fclose(f);
685
686 lockMixerCallback();
687 if (loadAsInstrFlag) // if loaded in instrument mode
688 {
689 freeInstr(editor.curInstr);
690 memset(song.instrName[editor.curInstr], 0, 23);
691 }
692
693 if (instr[editor.curInstr] == NULL)
694 allocateInstr(editor.curInstr);
695
696 if (instr[editor.curInstr] != NULL)
697 {
698 sampleTyp *s = &instr[editor.curInstr]->samp[sampleSlot];
699
700 freeSample(editor.curInstr, sampleSlot);
701 memcpy(s, &tmpSmp, sizeof (sampleTyp));
702 fixSample(s);
703 }
704 else
705 {
706 okBoxThreadSafe(0, "System message", "Not enough memory!");
707 goto aiffLoadError;
708 }
709 unlockMixerCallback();
710
711 fixSampleName(editor.curInstr);
712 setSongModifiedFlag();
713 stereoSampleLoadMode = -1;
714
715 // also sets mouse busy to false when done
716 editor.updateCurSmp = true;
717
718 return true;
719
720aiffLoadError:
721 if (f != NULL) fclose(f);
722 if (tmpSmp.origPek != NULL) free(tmpSmp.origPek);
723
724 stereoSampleLoadMode = -1;
725 sampleIsLoading = false;
726
727 return false;
728
729 (void)ptr;
730}
731
732static int32_t SDLCALL loadIFFSample(void *ptr)
733{
734 char hdr[4+1];
735 uint8_t i;
736 int32_t j;
737 uint32_t blockName, blockSize;
738 sampleTyp tmpSmp;
739
740 // this is important for the "goto" on load error
741 FILE *f = NULL;
742 memset(&tmpSmp, 0, sizeof (tmpSmp));
743
744 if (editor.tmpFilenameU == NULL)
745 {
746 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
747 goto iffLoadError;
748 }
749
750 UNICHAR *filename = editor.tmpFilenameU;
751
752 f = UNICHAR_FOPEN(filename, "rb");
753 if (f == NULL)
754 {
755 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
756 goto iffLoadError;
757 }
758
759 fseek(f, 0, SEEK_END);
760 int32_t filesize = ftell(f);
761 if (filesize < 12)
762 {
763 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
764 goto iffLoadError;
765 }
766
767 fseek(f, 8, SEEK_SET);
768 fread(hdr, 1, 4, f);
769 hdr[4] = '\0';
770 bool is16Bit = !strncmp(hdr, "16SV", 4);
771
772 uint32_t sampleLength = 0;
773 uint32_t sampleVol = 64;
774 uint32_t sampleLoopStart = 0;
775 uint32_t sampleLoopLength = 0;
776 uint16_t sampleRate = 16726;
777
778 uint32_t vhdrPtr = 0;
779 uint32_t vhdrLen = 0;
780 uint32_t bodyPtr = 0;
781 uint32_t bodyLen = 0;
782 uint32_t namePtr = 0;
783 uint32_t nameLen = 0;
784
785 fseek(f, 12, SEEK_SET);
786 while (!feof(f) && ftell(f) < filesize-12)
787 {
788 fread(&blockName, 4, 1, f); if (feof(f)) break;
789 fread(&blockSize, 4, 1, f); if (feof(f)) break;
790
791 blockName = SWAP32(blockName);
792 blockSize = SWAP32(blockSize);
793
794 switch (blockName)
795 {
796 case 0x56484452: // VHDR
797 {
798 vhdrPtr = ftell(f);
799 vhdrLen = blockSize;
800 }
801 break;
802
803 case 0x4E414D45: // NAME
804 {
805 namePtr = ftell(f);
806 nameLen = blockSize;
807 }
808 break;
809
810 case 0x424F4459: // BODY
811 {
812 bodyPtr = ftell(f);
813 bodyLen = blockSize;
814 }
815 break;
816
817 default: break;
818 }
819
820 fseek(f, blockSize + (blockSize & 1), SEEK_CUR);
821 }
822
823 if (vhdrPtr == 0 || vhdrLen < 20 || bodyPtr == 0)
824 {
825 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
826 goto iffLoadError;
827 }
828
829 // kludge for some really strange IFFs
830 if (bodyLen == 0)
831 bodyLen = filesize - bodyPtr;
832
833 if (bodyPtr+bodyLen > (uint32_t)filesize)
834 bodyLen = filesize - bodyPtr;
835
836 fseek(f, vhdrPtr, SEEK_SET);
837 fread(&sampleLoopStart, 4, 1, f); sampleLoopStart = SWAP32(sampleLoopStart);
838 fread(&sampleLoopLength, 4, 1, f); sampleLoopLength = SWAP32(sampleLoopLength);
839 fseek(f, 4, SEEK_CUR);
840 fread(&sampleRate, 2, 1, f); sampleRate = SWAP16(sampleRate);
841 fseek(f, 1, SEEK_CUR);
842
843 if (fgetc(f) != 0) // sample type
844 {
845 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported!");
846 goto iffLoadError;
847 }
848
849 fread(&sampleVol, 4, 1, f); sampleVol = SWAP32(sampleVol);
850 if (sampleVol > 65535)
851 sampleVol = 65535;
852
853 sampleVol = (int32_t)((sampleVol / 1024.0) + 0.5);
854 if (sampleVol > 64)
855 sampleVol = 64;
856
857 sampleLength = bodyLen;
858 if (sampleLength > MAX_SAMPLE_LEN)
859 sampleLength = MAX_SAMPLE_LEN;
860
861 if (sampleLoopStart >= MAX_SAMPLE_LEN || sampleLoopLength > MAX_SAMPLE_LEN)
862 {
863 sampleLoopStart = 0;
864 sampleLoopLength = 0;
865 }
866
867 if (sampleLoopStart+sampleLoopLength > sampleLength)
868 {
869 sampleLoopStart = 0;
870 sampleLoopLength = 0;
871 }
872
873 if (sampleLoopStart > sampleLength-2)
874 {
875 sampleLoopStart = 0;
876 sampleLoopLength = 0;
877 }
878
879 tmpSmp.pan = 128;
880 tmpSmp.vol = 64;
881
882 tmpSmp.origPek = (int8_t *)malloc(sampleLength + LOOP_FIX_LEN);
883 if (tmpSmp.origPek == NULL)
884 {
885 okBoxThreadSafe(0, "System message", "Not enough memory!");
886 goto iffLoadError;
887 }
888
889 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
890
891 fseek(f, bodyPtr, SEEK_SET);
892 if (fread(tmpSmp.pek, sampleLength, 1, f) != 1)
893 {
894 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
895 goto iffLoadError;
896 }
897
898 // set sample attributes
899 tmpSmp.len = sampleLength;
900
901 if (sampleLoopLength > 2)
902 {
903 tmpSmp.repS = sampleLoopStart;
904 tmpSmp.repL = sampleLoopLength;
905 tmpSmp.typ |= 1;
906 }
907
908 if (is16Bit)
909 {
910 tmpSmp.len &= 0xFFFFFFFE;
911 tmpSmp.repS &= 0xFFFFFFFE;
912 tmpSmp.repL &= 0xFFFFFFFE;
913 tmpSmp.typ |= 16;
914 }
915
916 tmpSmp.vol = (uint8_t)sampleVol;
917 tmpSmp.pan = 128;
918
919 tuneSample(&tmpSmp, sampleRate, audio.linearPeriodsFlag);
920
921 // set name
922 if (namePtr != 0 && nameLen > 0)
923 {
924 fseek(f, namePtr, SEEK_SET);
925 if (nameLen > 21)
926 {
927 tmpSmp.name[21] = '\0';
928 fread(tmpSmp.name, 1, 21, f);
929 }
930 else
931 {
932 memset(tmpSmp.name, 0, 22);
933 fread(tmpSmp.name, 1, nameLen, f);
934 }
935 }
936 else
937 {
938 // set sample name from filename if we didn't load name from .wav
939 char *tmpFilename = unicharToCp437(filename, true);
940 if (tmpFilename != NULL)
941 {
942 j = (int32_t)strlen(tmpFilename);
943 while (j--)
944 {
945 if (tmpFilename[j] == DIR_DELIMITER)
946 break;
947 }
948
949 char *tmpPtr = tmpFilename;
950 if (j > 0)
951 tmpPtr += j + 1;
952
953 sanitizeFilename(tmpPtr);
954
955 uint32_t filenameLen = (uint32_t)strlen(tmpPtr);
956 for (i = 0; i < 22; i++)
957 {
958 if (i < filenameLen)
959 tmpSmp.name[i] = tmpPtr[i];
960 else
961 tmpSmp.name[i] = '\0';
962 }
963
964 free(tmpFilename);
965 }
966 }
967
968 fclose(f);
969
970 lockMixerCallback();
971 if (loadAsInstrFlag) // if loaded in instrument mode
972 {
973 freeInstr(editor.curInstr);
974 memset(song.instrName[editor.curInstr], 0, 23);
975 }
976
977 if (instr[editor.curInstr] == NULL)
978 allocateInstr(editor.curInstr);
979
980 if (instr[editor.curInstr] != NULL)
981 {
982 sampleTyp *s = &instr[editor.curInstr]->samp[sampleSlot];
983
984 freeSample(editor.curInstr, sampleSlot);
985 memcpy(s, &tmpSmp, sizeof (sampleTyp));
986 fixSample(s);
987 }
988 else
989 {
990 okBoxThreadSafe(0, "System message", "Not enough memory!");
991 goto iffLoadError;
992 }
993 unlockMixerCallback();
994
995 fixSampleName(editor.curInstr);
996 setSongModifiedFlag();
997 stereoSampleLoadMode = -1;
998
999 // also sets mouse busy to false when done
1000 editor.updateCurSmp = true;
1001
1002 return true;
1003
1004iffLoadError:
1005 if (f != NULL) fclose(f);
1006 if (tmpSmp.origPek != NULL) free(tmpSmp.origPek);
1007
1008 stereoSampleLoadMode = -1;
1009 sampleIsLoading = false;
1010
1011 return false;
1012
1013 (void)ptr;
1014}
1015
1016static int32_t SDLCALL loadRawSample(void *ptr)
1017{
1018 int32_t j;
1019 uint32_t i;
1020 sampleTyp tmpSmp;
1021
1022 // this is important for the "goto" on load error
1023 FILE *f = NULL;
1024 memset(&tmpSmp, 0, sizeof (tmpSmp));
1025
1026 if (editor.tmpFilenameU == NULL)
1027 {
1028 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1029 goto rawLoadError;
1030 }
1031
1032 UNICHAR *filename = editor.tmpFilenameU;
1033
1034 f = UNICHAR_FOPEN(filename, "rb");
1035 if (f == NULL)
1036 {
1037 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1038 goto rawLoadError;
1039 }
1040
1041 fseek(f, 0, SEEK_END);
1042 uint32_t filesize = ftell(f);
1043 rewind(f);
1044
1045 if (filesize > MAX_SAMPLE_LEN)
1046 filesize = MAX_SAMPLE_LEN;
1047
1048 if (filesize == 0)
1049 {
1050 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
1051 goto rawLoadError;
1052 }
1053
1054 tmpSmp.pan = 128;
1055 tmpSmp.vol = 64;
1056
1057 tmpSmp.origPek = (int8_t *)malloc(filesize + LOOP_FIX_LEN);
1058 if (tmpSmp.origPek == NULL)
1059 {
1060 okBoxThreadSafe(0, "System message", "Not enough memory!");
1061 goto rawLoadError;
1062 }
1063
1064 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
1065
1066 if (fread(tmpSmp.pek, filesize, 1, f) != 1)
1067 {
1068 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1069 goto rawLoadError;
1070 }
1071
1072 fclose(f);
1073
1074 char *tmpFilename = unicharToCp437(filename, true);
1075 if (tmpFilename != NULL)
1076 {
1077 j = (int32_t)strlen(tmpFilename);
1078 while (j--)
1079 {
1080 if (tmpFilename[j] == DIR_DELIMITER)
1081 break;
1082 }
1083
1084 char *tmpPtr = tmpFilename;
1085 if (j > 0)
1086 tmpPtr += j + 1;
1087
1088 sanitizeFilename(tmpPtr);
1089
1090 uint32_t filenameLen = (uint32_t)strlen(tmpPtr);
1091 for (i = 0; i < 22; i++)
1092 {
1093 if (i < filenameLen)
1094 tmpSmp.name[i] = tmpPtr[i];
1095 else
1096 tmpSmp.name[i] = '\0';
1097 }
1098
1099 free(tmpFilename);
1100 }
1101
1102 tmpSmp.len = filesize;
1103 tmpSmp.vol = 64;
1104 tmpSmp.pan = 128;
1105
1106 lockMixerCallback();
1107 if (loadAsInstrFlag) // if loaded in instrument mode
1108 {
1109 freeInstr(editor.curInstr);
1110 memset(song.instrName[editor.curInstr], 0, 23);
1111 }
1112
1113 if (instr[editor.curInstr] == NULL)
1114 allocateInstr(editor.curInstr);
1115
1116 if (instr[editor.curInstr] != NULL)
1117 {
1118 sampleTyp *s = &instr[editor.curInstr]->samp[sampleSlot];
1119
1120 freeSample(editor.curInstr, sampleSlot);
1121 memcpy(s, &tmpSmp, sizeof (sampleTyp));
1122 fixSample(s);
1123 }
1124 else
1125 {
1126 okBoxThreadSafe(0, "System message", "Not enough memory!");
1127 goto rawLoadError;
1128 }
1129 unlockMixerCallback();
1130
1131 fixSampleName(editor.curInstr);
1132 setSongModifiedFlag();
1133 stereoSampleLoadMode = -1;
1134
1135 // also sets mouse busy to false when done
1136 editor.updateCurSmp = true;
1137
1138 return true;
1139
1140rawLoadError:
1141 if (f != NULL) fclose(f);
1142 if (tmpSmp.origPek != NULL) free(tmpSmp.origPek);
1143
1144 stereoSampleLoadMode = -1;
1145 sampleIsLoading = false;
1146
1147 return false;
1148
1149 (void)ptr;
1150}
1151
1152static int32_t SDLCALL loadWAVSample(void *ptr)
1153{
1154 char chr, *tmpFilename, *tmpPtr;
1155 int8_t *newPtr;
1156 uint8_t *audioDataU8;
1157 int16_t *audioDataS16, *audioDataS16_2, *ptr16;
1158 uint16_t audioFormat, numChannels, bitsPerSample, tempPan, tempVol;
1159 int32_t j, *audioDataS32, smp32;
1160 uint32_t filenameLen, i, sampleRate, chunkID, chunkSize, sampleLength, filesize;
1161 uint32_t numLoops, loopType, loopStart, loopEnd, bytesRead, endOfChunk, dataPtr, dataLen, fmtPtr;
1162 uint32_t fmtLen, inamPtr, inamLen, smplPtr, smplLen, xtraPtr, xtraLen, xtraFlags, len32;
1163 int64_t smp64;
1164 float *fAudioDataFloat;
1165 double *dAudioDataDouble;
1166 sampleTyp tmpSmp, *s;
1167
1168 // this is important for the "goto" on load error
1169 FILE *f = NULL;
1170 memset(&tmpSmp, 0, sizeof (tmpSmp));
1171
1172 // zero out chunk pointers and lengths
1173 fmtPtr = 0; fmtLen = 0;
1174 dataPtr = 0; dataLen = 0;
1175 inamPtr = 0; inamLen = 0;
1176 xtraPtr = 0; xtraLen = 0;
1177 smplPtr = 0; smplLen = 0;
1178
1179 if (editor.tmpFilenameU == NULL)
1180 {
1181 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1182 goto wavLoadError;
1183 }
1184
1185 UNICHAR *filename = editor.tmpFilenameU;
1186
1187 f = UNICHAR_FOPEN(filename, "rb");
1188 if (f == NULL)
1189 {
1190 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1191 goto wavLoadError;
1192 }
1193
1194 // get and check filesize
1195 fseek(f, 0, SEEK_END);
1196 filesize = ftell(f);
1197 if (filesize < 12)
1198 {
1199 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
1200 goto wavLoadError;
1201 }
1202
1203 // look for wanted chunks and set up pointers + lengths
1204 fseek(f, 12, SEEK_SET);
1205
1206 bytesRead = 0;
1207 while (!feof(f) && bytesRead < filesize-12)
1208 {
1209 fread(&chunkID, 4, 1, f); if (feof(f)) break;
1210 fread(&chunkSize, 4, 1, f); if (feof(f)) break;
1211
1212 endOfChunk = (ftell(f) + chunkSize) + (chunkSize & 1);
1213 switch (chunkID)
1214 {
1215 case 0x20746D66: // "fmt "
1216 {
1217 fmtPtr = ftell(f);
1218 fmtLen = chunkSize;
1219 }
1220 break;
1221
1222 case 0x61746164: // "data"
1223 {
1224 dataPtr = ftell(f);
1225 dataLen = chunkSize;
1226 }
1227 break;
1228
1229 case 0x5453494C: // "LIST"
1230 {
1231 if (chunkSize >= 4)
1232 {
1233 fread(&chunkID, 4, 1, f);
1234 if (chunkID == 0x4F464E49) // "INFO"
1235 {
1236 bytesRead = 0;
1237 while (!feof(f) && bytesRead < chunkSize)
1238 {
1239 fread(&chunkID, 4, 1, f);
1240 fread(&chunkSize, 4, 1, f);
1241
1242 switch (chunkID)
1243 {
1244 case 0x4D414E49: // "INAM"
1245 {
1246 inamPtr = ftell(f);
1247 inamLen = chunkSize;
1248 }
1249 break;
1250
1251 default: break;
1252 }
1253
1254 bytesRead += (chunkSize + (chunkSize & 1));
1255 }
1256 }
1257 }
1258 }
1259 break;
1260
1261 case 0x61727478: // "xtra"
1262 {
1263 xtraPtr = ftell(f);
1264 xtraLen = chunkSize;
1265 }
1266 break;
1267
1268 case 0x6C706D73: // "smpl"
1269 {
1270 smplPtr = ftell(f);
1271 smplLen = chunkSize;
1272 }
1273 break;
1274
1275 default: break;
1276 }
1277
1278 bytesRead += (chunkSize + (chunkSize & 1));
1279 fseek(f, endOfChunk, SEEK_SET);
1280 }
1281
1282 // we need at least "fmt " and "data" - check if we found them sanely
1283 if ((fmtPtr == 0 || fmtLen < 16) || (dataPtr == 0 || dataLen == 0))
1284 {
1285 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
1286 goto wavLoadError;
1287 }
1288
1289 // ---- READ "fmt " CHUNK ----
1290 fseek(f, fmtPtr, SEEK_SET);
1291 fread(&audioFormat, 2, 1, f);
1292 fread(&numChannels, 2, 1, f);
1293 fread(&sampleRate, 4, 1, f);
1294 fseek(f, 6, SEEK_CUR); // unneeded
1295 fread(&bitsPerSample, 2, 1, f);
1296 sampleLength = dataLen;
1297 // ---------------------------
1298
1299 // test if the WAV is compatible with our loader
1300
1301 if (sampleRate == 0 || sampleLength == 0 || sampleLength >= filesize)
1302 {
1303 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported or is invalid!");
1304 goto wavLoadError;
1305 }
1306
1307 if (audioFormat != WAV_FORMAT_PCM && audioFormat != WAV_FORMAT_IEEE_FLOAT)
1308 {
1309 okBoxThreadSafe(0, "System message", "Error loading sample: The sample is not supported!");
1310 goto wavLoadError;
1311 }
1312
1313 if (numChannels == 0 || numChannels > 2)
1314 {
1315 okBoxThreadSafe(0, "System message", "Error loading sample: Unsupported number of channels!");
1316 goto wavLoadError;
1317 }
1318
1319 if (audioFormat == WAV_FORMAT_IEEE_FLOAT && bitsPerSample != 32 && bitsPerSample != 64)
1320 {
1321 okBoxThreadSafe(0, "System message", "Error loading sample: Unsupported bitdepth!");
1322 goto wavLoadError;
1323 }
1324
1325 if (bitsPerSample != 8 && bitsPerSample != 16 && bitsPerSample != 24 && bitsPerSample != 32 && bitsPerSample != 64)
1326 {
1327 okBoxThreadSafe(0, "System message", "Error loading sample: Unsupported bitdepth!");
1328 goto wavLoadError;
1329 }
1330
1331 // ---- READ SAMPLE DATA ----
1332 fseek(f, dataPtr, SEEK_SET);
1333
1334 s = &instr[editor.curInstr]->samp[editor.curSmp];
1335 tmpSmp.pan = 128;
1336 tmpSmp.vol = 64;
1337
1338 if (sampleLength > MAX_SAMPLE_LEN)
1339 sampleLength = MAX_SAMPLE_LEN;
1340
1341 if (bitsPerSample == 8) // 8-BIT INTEGER SAMPLE
1342 {
1343 tmpSmp.origPek = (int8_t *)malloc(sampleLength + LOOP_FIX_LEN);
1344 if (tmpSmp.origPek == NULL)
1345 {
1346 okBoxThreadSafe(0, "System message", "Not enough memory!");
1347 goto wavLoadError;
1348 }
1349
1350 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
1351
1352 if (fread(tmpSmp.pek, sampleLength, 1, f) != 1)
1353 {
1354 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1355 goto wavLoadError;
1356 }
1357
1358 audioDataU8 = (uint8_t *)tmpSmp.pek;
1359
1360 // stereo conversion
1361 if (numChannels == 2)
1362 {
1363 sampleLength /= 2;
1364 switch (stereoSampleLoadMode)
1365 {
1366 case STEREO_SAMPLE_READ_LEFT:
1367 {
1368 // remove right channel data
1369 for (i = 1; i < sampleLength; i++)
1370 audioDataU8[i] = audioDataU8[(i * 2) + 0];
1371 }
1372 break;
1373
1374 case STEREO_SAMPLE_READ_RIGHT:
1375 {
1376 // remove left channel data
1377 len32 = sampleLength - 1;
1378 for (i = 0; i < len32; i++)
1379 audioDataU8[i] = audioDataU8[(i * 2) + 1];
1380
1381 audioDataU8[i] = 128;
1382 }
1383 break;
1384
1385 default:
1386 case STEREO_SAMPLE_CONVERT:
1387 {
1388 // mix stereo to mono
1389 len32 = sampleLength - 1;
1390 for (i = 0; i < len32; i++)
1391 audioDataU8[i] = (audioDataU8[(i * 2) + 0] + audioDataU8[(i * 2) + 1]) >> 1;
1392
1393 audioDataU8[i] = 128;
1394 }
1395 break;
1396 }
1397 }
1398
1399 // convert from unsigned to signed
1400 for (i = 0; i < sampleLength; i++)
1401 tmpSmp.pek[i] ^= 0x80;
1402
1403 tmpSmp.typ &= ~16; // 8-bit
1404 }
1405 else if (bitsPerSample == 16) // 16-BIT INTEGER SAMPLE
1406 {
1407 sampleLength /= 2;
1408
1409 tmpSmp.origPek = (int8_t *)malloc((sampleLength * 2) + LOOP_FIX_LEN);
1410 if (tmpSmp.origPek == NULL)
1411 {
1412 okBoxThreadSafe(0, "System message", "Not enough memory!");
1413 goto wavLoadError;
1414 }
1415
1416 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
1417
1418 if (fread(tmpSmp.pek, sampleLength, 2, f) != 2)
1419 {
1420 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1421 goto wavLoadError;
1422 }
1423
1424 audioDataS16 = (int16_t *)tmpSmp.pek;
1425
1426 // stereo conversion
1427 if (numChannels == 2)
1428 {
1429 sampleLength /= 2;
1430
1431 switch (stereoSampleLoadMode)
1432 {
1433 case STEREO_SAMPLE_READ_LEFT:
1434 {
1435 // remove right channel data
1436 for (i = 1; i < sampleLength; i++)
1437 audioDataS16[i] = audioDataS16[(i * 2) + 0];
1438 }
1439 break;
1440
1441 case STEREO_SAMPLE_READ_RIGHT:
1442 {
1443 // remove left channel data
1444 len32 = sampleLength - 1;
1445 for (i = 0; i < len32; i++)
1446 audioDataS16[i] = audioDataS16[(i * 2) + 1];
1447
1448 audioDataS16[i] = 0;
1449 }
1450 break;
1451
1452 default:
1453 case STEREO_SAMPLE_CONVERT:
1454 {
1455 // mix stereo to mono
1456 len32 = sampleLength - 1;
1457 for (i = 0; i < len32; i++)
1458 {
1459 smp32 = audioDataS16[(i * 2) + 0] + audioDataS16[(i * 2) + 1];
1460 audioDataS16[i] = (int16_t)(smp32 >> 1);
1461 }
1462
1463 audioDataS16[i] = 0;
1464 }
1465 break;
1466 }
1467 }
1468
1469 sampleLength *= 2;
1470 tmpSmp.typ |= 16; // 16-bit
1471 }
1472 else if (bitsPerSample == 24) // 24-BIT INTEGER SAMPLE
1473 {
1474 sampleLength /= 3;
1475
1476 tmpSmp.origPek = (int8_t *)malloc(((sampleLength * 4) * 2) + LOOP_FIX_LEN);
1477 if (tmpSmp.origPek == NULL)
1478 {
1479 okBoxThreadSafe(0, "System message", "Not enough memory!");
1480 goto wavLoadError;
1481 }
1482
1483 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
1484
1485 if (fread(&tmpSmp.pek[sampleLength], sampleLength, 3, f) != 3)
1486 {
1487 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1488 goto wavLoadError;
1489 }
1490
1491 audioDataS32 = (int32_t *)tmpSmp.pek;
1492
1493 // convert to 32-bit
1494 audioDataU8 = (uint8_t *)tmpSmp.pek + sampleLength;
1495 for (i = 0; i < sampleLength; i++)
1496 {
1497 audioDataS32[i] = (audioDataU8[2] << 24) | (audioDataU8[1] << 16) | (audioDataU8[0] << 8);
1498 audioDataU8 += 3;
1499 }
1500
1501 // stereo conversion
1502 if (numChannels == 2)
1503 {
1504 sampleLength /= 2;
1505 switch (stereoSampleLoadMode)
1506 {
1507 case STEREO_SAMPLE_READ_LEFT:
1508 {
1509 // remove right channel data
1510 for (i = 1; i < sampleLength; i++)
1511 audioDataS32[i] = audioDataS32[(i * 2) + 0];
1512 }
1513 break;
1514
1515 case STEREO_SAMPLE_READ_RIGHT:
1516 {
1517 // remove left channel data
1518 len32 = sampleLength - 1;
1519 for (i = 0; i < len32; i++)
1520 audioDataS32[i] = audioDataS32[(i * 2) + 1];
1521
1522 audioDataS32[i] = 0;
1523 }
1524 break;
1525
1526 default:
1527 case STEREO_SAMPLE_CONVERT:
1528 {
1529 // mix stereo to mono
1530 len32 = sampleLength - 1;
1531 for (i = 0; i < len32; i++)
1532 {
1533 smp64 = audioDataS32[(i * 2) + 0];
1534 smp64 += audioDataS32[(i * 2) + 1];
1535 smp64 >>= 1;
1536
1537 audioDataS32[i] = (int32_t)smp64;
1538 }
1539
1540 audioDataS32[i] = 0;
1541 }
1542 break;
1543 }
1544 }
1545
1546 normalize32bitSigned(audioDataS32, sampleLength);
1547
1548 // downscale to 16-bit (ultra fast method!)
1549
1550 audioDataS16 = (int16_t *)tmpSmp.pek;
1551 audioDataS16_2 = (int16_t *)tmpSmp.pek + 1;
1552
1553 for (i = 0; i < sampleLength; i++)
1554 {
1555 audioDataS16[i] = audioDataS16_2[i];
1556 audioDataS16_2++;
1557 }
1558
1559 sampleLength *= 2;
1560 tmpSmp.typ |= 16; // 16-bit
1561 }
1562 else if (audioFormat == WAV_FORMAT_PCM && bitsPerSample == 32) // 32-BIT INTEGER SAMPLE
1563 {
1564 sampleLength /= 4;
1565
1566 tmpSmp.origPek = (int8_t *)malloc((sampleLength * 4) + LOOP_FIX_LEN);
1567 if (tmpSmp.origPek == NULL)
1568 {
1569 okBoxThreadSafe(0, "System message", "Not enough memory!");
1570 goto wavLoadError;
1571 }
1572
1573 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
1574
1575 if (fread(tmpSmp.pek, sampleLength, 4, f) != 4)
1576 {
1577 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1578 goto wavLoadError;
1579 }
1580
1581 audioDataS32 = (int32_t *)tmpSmp.pek;
1582
1583 // stereo conversion
1584 if (numChannels == 2)
1585 {
1586 sampleLength /= 2;
1587 switch (stereoSampleLoadMode)
1588 {
1589 case STEREO_SAMPLE_READ_LEFT:
1590 {
1591 // remove right channel data
1592 for (i = 1; i < sampleLength; i++)
1593 audioDataS32[i] = audioDataS32[(i * 2) + 0];
1594 }
1595 break;
1596
1597 case STEREO_SAMPLE_READ_RIGHT:
1598 {
1599 // remove left channel data
1600 len32 = sampleLength - 1;
1601 for (i = 0; i < len32; i++)
1602 audioDataS32[i] = audioDataS32[(i * 2) + 1];
1603
1604 audioDataS32[i] = 0;
1605 }
1606 break;
1607
1608 default:
1609 case STEREO_SAMPLE_CONVERT:
1610 {
1611 // mix stereo to mono
1612 len32 = sampleLength - 1;
1613 for (i = 0; i < len32; i++)
1614 {
1615 smp64 = audioDataS32[(i * 2) + 0];
1616 smp64 += audioDataS32[(i * 2) + 1];
1617 smp64 >>= 1;
1618
1619 audioDataS32[i] = (int32_t)smp64;
1620 }
1621
1622 audioDataS32[i] = 0;
1623 }
1624 break;
1625 }
1626 }
1627
1628 normalize32bitSigned(audioDataS32, sampleLength);
1629
1630 // downscale to 16-bit (ultra fast method!)
1631
1632 audioDataS16 = (int16_t *)tmpSmp.pek;
1633 audioDataS16_2 = (int16_t *)tmpSmp.pek + 1;
1634
1635 for (i = 0; i < sampleLength; i++)
1636 {
1637 audioDataS16[i] = audioDataS16_2[i];
1638 audioDataS16_2++;
1639 }
1640
1641 sampleLength *= 2;
1642 tmpSmp.typ |= 16; // 16-bit
1643 }
1644 else if (audioFormat == WAV_FORMAT_IEEE_FLOAT && bitsPerSample == 32) // 32-BIT FLOATING POINT SAMPLE
1645 {
1646 sampleLength /= 4;
1647 31
1648 tmpSmp.origPek = (int8_t *)malloc((sampleLength * 4) + LOOP_FIX_LEN);32// file extensions accepted by Disk Op. in sample mode
1649 if (tmpSmp.origPek == NULL)33char *supportedSmpExtensions[] =
1650 {34{
1651 okBoxThreadSafe(0, "System message", "Not enough memory!");35 "iff", "raw", "wav", "snd", "smp", "sam", "aif", "pat", "aiff",
1652 goto wavLoadError;
1653 }
1654 36
1655 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;37 "END_OF_LIST" // do NOT move, remove or edit this line!
38};
1656 39
1657 if (fread(tmpSmp.pek, sampleLength, 4, f) != 4)40// globals for sample loaders
1658 {41bool loadAsInstrFlag, smpFilenameSet;
1659 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");42char *smpFilename;
1660 goto wavLoadError;43uint8_t sampleSlot;
1661 }44sampleTyp tmpSmp;
45// --------------------------
1662 46
1663 fAudioDataFloat = (float *)tmpSmp.pek;47static volatile bool sampleIsLoading;
48static SDL_Thread *thread;
1664 49
1665 // stereo conversion50static void freeTmpSample(sampleTyp *s);
1666 if (numChannels == 2)
1667 {
1668 sampleLength /= 2;
1669 switch (stereoSampleLoadMode)
1670 {
1671 case STEREO_SAMPLE_READ_LEFT:
1672 {
1673 // remove right channel data
1674 for (i = 1; i < sampleLength; i++)
1675 fAudioDataFloat[i] = fAudioDataFloat[(i * 2) + 0];
1676 }
1677 break;
1678 51
1679 case STEREO_SAMPLE_READ_RIGHT:52// Crude sample detection routine. These aren't always accurate detections!
1680 {53static int8_t detectSample(FILE *f)
1681 // remove left channel data54{
1682 len32 = sampleLength - 1;55 uint8_t D[256];
1683 for (i = 0; i < len32; i++)
1684 fAudioDataFloat[i] = fAudioDataFloat[(i * 2) + 1];
1685 56
1686 fAudioDataFloat[i] = 0.0f;57 uint32_t oldPos = ftell(f);
1687 }58 rewind(f);
1688 break;59 memset(D, 0, sizeof (D));
60 fread(D, 1, sizeof (D), f);
61 fseek(f, oldPos, SEEK_SET);
1689 62
1690 default:63 if (!memcmp("FORM", &D[0], 4) && (!memcmp("8SVX", &D[8], 4) || !memcmp("16SV", &D[8], 4)))
1691 case STEREO_SAMPLE_CONVERT:64 return FORMAT_IFF;
1692 {
1693 // mix stereo to mono
1694 len32 = sampleLength - 1;
1695 for (i = 0; i < len32; i++)
1696 fAudioDataFloat[i] = (fAudioDataFloat[(i * 2) + 0] + fAudioDataFloat[(i * 2) + 1]) * 0.5f;
1697 65
1698 fAudioDataFloat[i] = 0.0f;66 if (!memcmp("RIFF", &D[0], 4) && !memcmp("WAVE", &D[8], 4))
1699 }67 return FORMAT_WAV;
1700 break;
1701 }
1702 }
1703 68
1704 normalize16bitFloatSigned(fAudioDataFloat, sampleLength);69 if (!memcmp("FORM", &D[0], 4) && (!memcmp("AIFF", &D[8], 4) || !memcmp("AIFC", &D[8], 4)))
70 return FORMAT_AIFF;
1705 71
1706 ptr16 = (int16_t *)tmpSmp.pek;72 return FORMAT_UNKNOWN;
1707 for (i = 0; i < sampleLength; i++)73}
1708 ptr16[i] = (int16_t)fAudioDataFloat[i]; // should use SIMD if available
1709 74
1710 sampleLength *= 2;75static int32_t SDLCALL loadSampleThread(void *ptr)
1711 tmpSmp.typ |= 16; // 16-bit76{
1712 }77 if (editor.tmpFilenameU == NULL)
1713 else if (audioFormat == WAV_FORMAT_IEEE_FLOAT && bitsPerSample == 64) // 64-BIT FLOATING POINT SAMPLE
1714 {78 {
1715 sampleLength /= 8;79 loaderMsgBox("General I/O error during loading!");
1716 80 return false;
1717 tmpSmp.origPek = (int8_t *)malloc((sampleLength * 8) + LOOP_FIX_LEN);
1718 if (tmpSmp.origPek == NULL)
1719 {
1720 okBoxThreadSafe(0, "System message", "Not enough memory!");
1721 goto wavLoadError;
1722 }
1723
1724 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;
1725
1726 if (fread(tmpSmp.pek, sampleLength, 8, f) != 8)
1727 {
1728 okBoxThreadSafe(0, "System message", "General I/O error during loading! Is the file in use?");
1729 goto wavLoadError;
1730 }
1731
1732 dAudioDataDouble = (double *)tmpSmp.pek;
1733
1734 // stereo conversion
1735 if (numChannels == 2)
1736 {
1737 sampleLength /= 2;
1738 switch (stereoSampleLoadMode)
1739 {
1740 case STEREO_SAMPLE_READ_LEFT:
1741 {
1742 // remove right channel data
1743 for (i = 1; i < sampleLength; i++)
1744 dAudioDataDouble[i] = dAudioDataDouble[(i * 2) + 0];
1745 }
1746 break;
1747
1748 case STEREO_SAMPLE_READ_RIGHT:
1749 {
1750 // remove left channel data
1751 len32 = sampleLength - 1;
1752 for (i = 0; i < len32; i++)
1753 dAudioDataDouble[i] = dAudioDataDouble[(i * 2) + 1];
1754
1755 dAudioDataDouble[i] = 0.0;
1756 }
1757 break;
1758
1759 default:
1760 case STEREO_SAMPLE_CONVERT:
1761 {
1762 // mix stereo to mono
1763 len32 = sampleLength - 1;
1764 for (i = 0; i < len32; i++)
1765 dAudioDataDouble[i] = (dAudioDataDouble[(i * 2) + 0] + dAudioDataDouble[(i * 2) + 1]) * 0.5;
1766
1767 dAudioDataDouble[i] = 0.0;
1768 }
1769 break;
1770 }
1771 }
1772
1773 normalize64bitDoubleSigned(dAudioDataDouble, sampleLength);
1774
1775 ptr16 = (int16_t *)tmpSmp.pek;
1776 for (i = 0; i < sampleLength; i++)
1777 ptr16[i] = (int16_t)dAudioDataDouble[i]; // should use SIMD if available
1778
1779 sampleLength *= 2;
1780 tmpSmp.typ |= 16; // 16-bit
1781 }81 }
1782 82
1783 // adjust memory needed83 FILE *f = UNICHAR_FOPEN(editor.tmpFilenameU, "rb");
1784 newPtr = (int8_t *)realloc(tmpSmp.origPek, sampleLength + LOOP_FIX_LEN);84 if (f == NULL)
1785 if (newPtr != NULL)
1786 {85 {
1787 tmpSmp.origPek = newPtr;86 loaderMsgBox("General I/O error during loading! Is the file in use?");
1788 tmpSmp.pek = tmpSmp.origPek + SMP_DAT_OFFSET;87 return false;
1789 }88 }
1790 89
1791 tuneSample(&tmpSmp, sampleRate, audio.linearPeriodsFlag);90 int8_t format = detectSample(f);
1792 91 fseek(f, 0, SEEK_END);
1793 tmpSmp.vol = 64;92 uint32_t filesize = ftell(f);
1794 tmpSmp.pan = 128;
1795 tmpSmp.len = sampleLength;
1796 93
1797 // ---- READ "smpl" chunk ----94 if (filesize == 0)
1798 if (smplPtr != 0 && smplLen > 52)
1799 {95 {
1800 fseek(f, smplPtr + 28, SEEK_SET); // seek to first wanted byte96 fclose(f);
1801 97 loaderMsgBox("Error loading sample: The file is empty!");
1802 fread(&numLoops, 4, 1, f);98 return false;
1803 if (numLoops == 1)
1804 {
1805 fseek(f, 4 + 4, SEEK_CUR); // skip "samplerData" and "identifier"
1806
1807 fread(&loopType, 4, 1, f);
1808 fread(&loopStart, 4, 1, f);
1809 fread(&loopEnd, 4, 1, f);
1810
1811 loopEnd++;
1812
1813 if (tmpSmp.typ & 16)
1814 {
1815 loopStart *= 2;
1816 loopEnd *= 2;
1817 }
1818
1819 if (loopEnd <= sampleLength)
1820 {
1821 tmpSmp.repS = loopStart;
1822 tmpSmp.repL = loopEnd - loopStart;
1823 tmpSmp.typ |= ((loopType == 0) ? 1 : 2);
1824 }
1825 }
1826 }99 }
1827 // ---------------------------
1828
1829 // ---- READ "xtra" chunk ----
1830 if (xtraPtr != 0 && xtraLen >= 8)
1831 {
1832 fseek(f, xtraPtr, SEEK_SET);
1833
1834 fread(&xtraFlags, 4, 1, f); // flags
1835 100
1836 // panning (0..256)101 bool sampleLoaded = false;
1837 if (xtraFlags & 0x20) // set panning flag
1838 {
1839 fread(&tempPan, 2, 1, f);
1840 if (tempPan > 255)
1841 tempPan = 255;
1842
1843 tmpSmp.pan = (uint8_t)tempPan;
1844 }
1845 else
1846 {
1847 // don't read panning, skip it
1848 fseek(f, 2, SEEK_CUR);
1849 }
1850
1851 // volume (0..256)
1852 fread(&tempVol, 2, 1, f);
1853 if (tempVol > 256)
1854 tempVol = 256;
1855
1856 tmpSmp.vol = (uint8_t)(tempVol / 4); // 0..256 -> 0..64
1857 }
1858 // ---------------------------
1859 102
1860 // ---- READ "INAM" chunk ----103 rewind(f);
1861 if (inamPtr != 0 && inamLen > 0)104 switch (format)
1862 {105 {
1863 fseek(f, inamPtr, SEEK_SET);106 case FORMAT_IFF: sampleLoaded = loadIFF(f, filesize); break;
107 case FORMAT_WAV: sampleLoaded = loadWAV(f, filesize); break;
108 case FORMAT_AIFF: sampleLoaded = loadAIFF(f, filesize); break;
109 default: sampleLoaded = loadRAW(f, filesize); break;
110 }
111 fclose(f);
1864 112
1865 memset(tmpSmp.name, 0, sizeof (tmpSmp.name));113 if (!sampleLoaded)
1866 for (i = 0; i < 22; i++)114 goto loadError;
1867 {
1868 if (i < inamLen)
1869 {
1870 chr = (char)fgetc(f);
1871 if (chr == '\0')
1872 break;
1873 115
1874 tmpSmp.name[i] = chr;116 // sample loaded successfully!
1875 }117
1876 }118 if (!smpFilenameSet) // if we didn't set a custom sample name in the loader, set it to its filename
1877 }
1878 else
1879 {119 {
1880 // set sample name from filename if we didn't load name from .wav120 char *tmpFilename = unicharToCp437(editor.tmpFilenameU, true);
1881 tmpFilename = unicharToCp437(filename, true);
1882 if (tmpFilename != NULL)121 if (tmpFilename != NULL)
1883 {122 {
1884 j = (int32_t)strlen(tmpFilename);123 int32_t i = (int32_t)strlen(tmpFilename);
1885 while (j--)124 while (i--)
1886 {125 {
1887 if (tmpFilename[j] == DIR_DELIMITER)126 if (tmpFilename[i] == DIR_DELIMITER)
1888 break;127 break;
1889 }128 }
1890 129
1891 tmpPtr = tmpFilename;130 char *tmpPtr = tmpFilename;
1892 if (j > 0)131 if (i > 0)
1893 tmpPtr += j + 1;132 tmpPtr += i+1;
1894 133
1895 sanitizeFilename(tmpPtr);134 sanitizeFilename(tmpPtr);
1896 135
1897 filenameLen = (uint32_t)strlen(tmpPtr);136 int32_t filenameLen = (int32_t)strlen(tmpPtr);
1898 for (i = 0; i < 22; i++)137 for (i = 0; i < 22; i++)
1899 {138 {
1900 if (i < filenameLen)139 if (i < filenameLen)
@@ -1907,7 +146,7 @@ static int32_t SDLCALL loadWAVSample(void *ptr) · 6 unmodified lines
1907 }146 }
1908 }147 }
1909 148
1910 fclose(f);149 fixString(tmpSmp.name, 21); // remove leading spaces from sample filename
1911 150
1912 lockMixerCallback();151 lockMixerCallback();
1913 if (loadAsInstrFlag) // if loaded in instrument mode152 if (loadAsInstrFlag) // if loaded in instrument mode
@@ -1919,172 +158,82 @@ static int32_t SDLCALL loadWAVSample(void *ptr) · 5 unmodified lines
1919 if (instr[editor.curInstr] == NULL)158 if (instr[editor.curInstr] == NULL)
1920 allocateInstr(editor.curInstr);159 allocateInstr(editor.curInstr);
1921 160
1922 if (instr[editor.curInstr] != NULL)161 if (instr[editor.curInstr] == NULL)
1923 {
1924 s = &instr[editor.curInstr]->samp[sampleSlot];
1925
1926 freeSample(editor.curInstr, sampleSlot);
1927 memcpy(s, &tmpSmp, sizeof (sampleTyp));
1928 fixSample(s);
1929 }
1930 else
1931 {162 {
1932 okBoxThreadSafe(0, "System message", "Not enough memory!");163 loaderMsgBox("Not enough memory!");
1933 goto wavLoadError;164 goto loadError;
1934 }165 }
166
167 sampleTyp *s = &instr[editor.curInstr]->samp[sampleSlot];
168
169 freeSample(editor.curInstr, sampleSlot);
170 memcpy(s, &tmpSmp, sizeof (sampleTyp));
171 fixSample(s); // prepares sample for branchless resampling interpolation
172 fixInstrAndSampleNames(editor.curInstr);
173
1935 unlockMixerCallback();174 unlockMixerCallback();
1936 175
1937 fixSampleName(editor.curInstr);
1938 setSongModifiedFlag();176 setSongModifiedFlag();
1939 stereoSampleLoadMode = -1;
1940 177
1941 // also sets mouse busy to false when done178 // when caught in main/video thread, it disables busy mouse and sets sampleIsLoading to true
1942 editor.updateCurSmp = true;179 editor.updateCurSmp = true;
1943 180
1944 return true;181 return true;
1945 182
1946wavLoadError:183loadError:
1947 if (f != NULL) fclose(f);184 setMouseBusy(false);
1948 if (tmpSmp.origPek != NULL) free(tmpSmp.origPek);185 freeTmpSample(&tmpSmp);
1949
1950 stereoSampleLoadMode = -1;
1951 sampleIsLoading = false;186 sampleIsLoading = false;
1952
1953 return false;187 return false;
1954 188
1955 (void)ptr;189 (void)ptr;
1956}190}
1957 191
1958bool loadSample(UNICHAR *filenameU, uint8_t smpNr, bool instrFlag)192static void freeTmpSample(sampleTyp *s)
1959{193{
1960 char tmpBuffer[16+1];194 if (s->origPek != NULL)
1961
1962 if (sampleIsLoading)
1963 return false;
1964
1965 stereoSampleLoadMode = 0;
1966
1967 sampleSlot = smpNr;
1968 loadAsInstrFlag = instrFlag;
1969
1970 if (editor.curInstr == 0)
1971 {
1972 okBox(0, "System message", "The zero-instrument cannot hold intrument data.");
1973 return false;
1974 }
1975
1976 FILE *f = UNICHAR_FOPEN(filenameU, "rb");
1977 if (f == NULL)
1978 {195 {
1979 okBox(0, "System message", "General I/O error during loading! Is the file in use?");196 free(s->origPek);
1980 return false;197 s->origPek = NULL;
1981 }198 }
1982 199
1983 memset(tmpBuffer, 0, sizeof (tmpBuffer));200 s->pek = NULL;
1984 if (fread(tmpBuffer, sizeof (tmpBuffer) - 1, 1, f) == 1)201}
1985 {
1986 tmpBuffer[sizeof (tmpBuffer) - 1] = '\0';
1987
1988 // detect what sample format this is...
1989
1990 // WAV
1991 if (!strncmp("RIFF", tmpBuffer, 4) && !strncmp("WAVE", tmpBuffer + 8, 4))
1992 {
1993 // let the user pick what to do with stereo samples...
1994 if (wavIsStereo(f))
1995 stereoSampleLoadMode = okBox(5, "System request", "This is a stereo sample...");
1996
1997 sampleIsLoading = true;
1998
1999 fclose(f);
2000 UNICHAR_STRCPY(editor.tmpFilenameU, filenameU);
2001
2002 mouseAnimOn();
2003 thread = SDL_CreateThread(loadWAVSample, NULL, NULL);
2004 if (thread == NULL)
2005 {
2006 okBox(0, "System message", "Couldn't create thread!");
2007 sampleIsLoading = false;
2008 return false;
2009 }
2010
2011 SDL_DetachThread(thread);
2012 return true;
2013 }
2014
2015 // AIFF or IFF
2016 if (!strncmp("FORM", tmpBuffer, 4))
2017 {
2018 if (!strncmp("AIFC", tmpBuffer + 8, 4))
2019 {
2020 // AIFC (not supported)
2021
2022 fclose(f);
2023 okBox(0, "System message", "Error loading sample: This AIFF type (AIFC) is not supported!");
2024 return true;
2025 }
2026 else if (!strncmp("AIFF", tmpBuffer + 8, 4))
2027 {
2028 // AIFF
2029
2030 // let the user pick what to do with stereo samples...
2031 if (aiffIsStereo(f))
2032 stereoSampleLoadMode = okBox(5, "System request", "This is a stereo sample...");
2033
2034 sampleIsLoading = true;
2035
2036 fclose(f);
2037 UNICHAR_STRCPY(editor.tmpFilenameU, filenameU);
2038
2039 mouseAnimOn();
2040 thread = SDL_CreateThread(loadAIFFSample, NULL, NULL);
2041 if (thread == NULL)
2042 {
2043 okBox(0, "System message", "Couldn't create thread!");
2044 sampleIsLoading = false;
2045 return false;
2046 }
2047
2048 SDL_DetachThread(thread);
2049 return true;
2050 }
2051 else if (!strncmp("8SVX", tmpBuffer + 8, 4) || !strncmp("16SV", tmpBuffer + 8, 4))
2052 {
2053 // IFF
2054 202
2055 sampleIsLoading = true;203void removeSampleIsLoadingFlag(void)
204{
205 sampleIsLoading = false;
206}
2056 207
2057 fclose(f);208bool loadSample(UNICHAR *filenameU, uint8_t smpNr, bool instrFlag)
2058 UNICHAR_STRCPY(editor.tmpFilenameU, filenameU);209{
210 if (sampleIsLoading || filenameU == NULL)
211 return false;
2059 212
2060 mouseAnimOn();213 // setup message box functions
2061 thread = SDL_CreateThread(loadIFFSample, NULL, NULL);214 loaderMsgBox = myLoaderMsgBoxThreadSafe;
2062 if (thread == NULL)215 loaderSysReq = okBoxThreadSafe;
2063 {
2064 okBox(0, "System message", "Couldn't create thread!");
2065 sampleIsLoading = false;
2066 return false;
2067 }
2068 216
2069 SDL_DetachThread(thread);217 if (editor.curInstr == 0)
2070 return true;218 {
2071 }219 loaderMsgBox("The zero-instrument cannot hold intrument data.");
2072 }220 return false;
2073 }221 }
2074 222
2075 // load as RAW sample223 sampleSlot = smpNr;
2076 224 loadAsInstrFlag = instrFlag;
2077 sampleIsLoading = true;225 sampleIsLoading = true;
226 smpFilenameSet = false;
2078 227
2079 fclose(f);228 memset(&tmpSmp, 0, sizeof (tmpSmp));
2080 UNICHAR_STRCPY(editor.tmpFilenameU, filenameU);229 UNICHAR_STRCPY(editor.tmpFilenameU, filenameU);
2081 230
2082 mouseAnimOn();231 mouseAnimOn();
2083 thread = SDL_CreateThread(loadRawSample, NULL, NULL);232 thread = SDL_CreateThread(loadSampleThread, NULL, NULL);
2084 if (thread == NULL)233 if (thread == NULL)
2085 {234 {
2086 okBox(0, "System message", "Couldn't create thread!");
2087 sampleIsLoading = false;235 sampleIsLoading = false;
236 loaderMsgBox("Couldn't create thread!");
2088 return false;237 return false;
2089 }238 }
2090 239
@@ -2092,7 +241,7 @@ bool loadSample(UNICHAR *filenameU, uint8_t smpNr, bool instrFlag) · 1 unmodified line
2092 return true;241 return true;
2093}242}
2094 243
2095static void normalize32bitSigned(int32_t *sampleData, uint32_t sampleLength)244void normalizeSigned32Bit(int32_t *sampleData, uint32_t sampleLength)
2096{245{
2097 uint32_t i;246 uint32_t i;
2098 247
@@ -2112,7 +261,7 @@ static void normalize32bitSigned(int32_t *sampleData, uint32_t sampleLength) · 13 unmodified lines
2112 sampleData[i] = (int32_t)(sampleData[i] * dGain);261 sampleData[i] = (int32_t)(sampleData[i] * dGain);
2113}262}
2114 263
2115static void normalize16bitFloatSigned(float *fSampleData, uint32_t sampleLength)264void normalize32BitFloatToSigned16Bit(float *fSampleData, uint32_t sampleLength)
2116{265{
2117 uint32_t i;266 uint32_t i;
2118 267
@@ -2132,7 +281,7 @@ static void normalize16bitFloatSigned(float *fSampleData, uint32_t sampleLength) · 13 unmodified lines
2132 fSampleData[i] *= fGain;281 fSampleData[i] *= fGain;
2133}282}
2134 283
2135static void normalize64bitDoubleSigned(double *dSampleData, uint32_t sampleLength)284void normalize64BitFloatToSigned16Bit(double *dSampleData, uint32_t sampleLength)
2136{285{
2137 uint32_t i;286 uint32_t i;
2138 287
@@ -2151,98 +300,3 @@ static void normalize64bitDoubleSigned(double *dSampleData, uint32_t sampleLengt · 12 unmodified lines
2151 for (i = 0; i < sampleLength; i++)300 for (i = 0; i < sampleLength; i++)
2152 dSampleData[i] *= dGain;301 dSampleData[i] *= dGain;
2153}302}
2154
2155bool fileIsInstrument(char *fullPath)
2156{
2157 int32_t i, len;
2158
2159 // this assumes that fullPath is not empty
2160
2161 len = (int32_t)strlen(fullPath);
2162
2163 // get filename from path
2164 i = len;
2165 while (i--)
2166 {
2167 if (fullPath[i] == DIR_DELIMITER)
2168 break;
2169 }
2170
2171 char *filename = fullPath;
2172 if (i > 0)
2173 filename += i + 1;
2174 // --------------------------
2175
2176 len = (int32_t)strlen(filename);
2177 if (len < 4)
2178 return true; // can't be an instrument
2179
2180 if (!_strnicmp("xi.", filename, 3) || (len >= 4 && !_strnicmp("pat.", filename, 4)))
2181 return true;
2182
2183 int32_t extOffset = getExtOffset(filename, len);
2184 if (extOffset != -1)
2185 {
2186 if ((extOffset <= len-4) && !_strnicmp(".pat", &filename[extOffset], 4)) return true;
2187 if ((extOffset <= len-3) && !_strnicmp(".xi", &filename[extOffset], 3)) return true;
2188 }
2189
2190 return false;
2191}
2192
2193bool fileIsSample(char *fullPath)
2194{
2195 int32_t i, len;
2196
2197 // this assumes that fullPath is not empty
2198
2199 len = (int32_t)strlen(fullPath);
2200
2201 // get filename from path
2202 i = len;
2203 while (i--)
2204 {
2205 if (fullPath[i] == DIR_DELIMITER)
2206 break;
2207 }
2208
2209 char *filename = fullPath;
2210 if (i > 0)
2211 filename += i + 1;
2212 // --------------------------
2213
2214 len = (int32_t)strlen(filename);
2215 if (len < 4)
2216 return true; // can't be a module
2217
2218 if (!_strnicmp("xm.", filename, 3) || !_strnicmp("ft.", filename, 3) ||
2219 !_strnicmp("mod.", filename, 4) || !_strnicmp("nst.", filename, 4) ||
2220 !_strnicmp("s3m.", filename, 4) || !_strnicmp("stm.", filename, 4) ||
2221 !_strnicmp("fst.", filename, 4) || !_strnicmp("it.", filename, 3))
2222 {
2223 return false; // definitely a module
2224 }
2225
2226 int32_t extOffset = getExtOffset(filename, len);
2227 if (extOffset != -1)
2228 {
2229 if (extOffset <= len-4)
2230 {
2231 filename = &filename[extOffset];
2232 if (!_strnicmp(".mod", filename, 4) || !_strnicmp(".nst", filename, 4) ||
2233 !_strnicmp(".s3m", filename, 4) || !_strnicmp(".stm", filename, 4) ||
2234 !_strnicmp(".fst", filename, 4))
2235 {
2236 return false; // definitely a module
2237 }
2238 }
2239 else if (extOffset <= len-3)
2240 {
2241 filename = &filename[extOffset];
2242 if (!_strnicmp(".xm", filename, 3) || !_strnicmp(".ft", filename, 3) || !_strnicmp(".it", filename, 3))
2243 return false; // definitely a module
2244 }
2245 }
2246
2247 return true; // let's assume it's a sample
2248}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t