LMMS
Loading...
Searching...
No Matches
juce_AiffAudioFormat.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24*/
25
26namespace juce
27{
28
29static const char* const aiffFormatName = "AIFF file";
30
31//==============================================================================
32const char* const AiffAudioFormat::appleOneShot = "apple one shot";
33const char* const AiffAudioFormat::appleRootSet = "apple root set";
34const char* const AiffAudioFormat::appleRootNote = "apple root note";
35const char* const AiffAudioFormat::appleBeats = "apple beats";
36const char* const AiffAudioFormat::appleDenominator = "apple denominator";
37const char* const AiffAudioFormat::appleNumerator = "apple numerator";
38const char* const AiffAudioFormat::appleTag = "apple tag";
39const char* const AiffAudioFormat::appleKey = "apple key";
40
41//==============================================================================
43{
44 inline int chunkName (const char* name) noexcept { return (int) ByteOrder::littleEndianInt (name); }
45
46 #if JUCE_MSVC
47 #pragma pack (push, 1)
48 #endif
49
50 //==============================================================================
51 struct InstChunk
52 {
53 struct Loop
54 {
55 uint16 type; // these are different in AIFF and WAV
59
69
70 void copyTo (std::map<String, String>& values) const
71 {
72 values.emplace ("MidiUnityNote", String (baseNote));
73 values.emplace ("Detune", String (detune));
74
75 values.emplace ("LowNote", String (lowNote));
76 values.emplace ("HighNote", String (highNote));
77 values.emplace ("LowVelocity", String (lowVelocity));
78 values.emplace ("HighVelocity", String (highVelocity));
79
80 values.emplace ("Gain", String ((int16) ByteOrder::swapIfLittleEndian ((uint16) gain)));
81
82 values.emplace ("NumSampleLoops", String (2)); // always 2 with AIFF, WAV can have more
83 values.emplace ("Loop0Type", String (ByteOrder::swapIfLittleEndian (sustainLoop.type)));
84 values.emplace ("Loop0StartIdentifier", String (ByteOrder::swapIfLittleEndian (sustainLoop.startIdentifier)));
85 values.emplace ("Loop0EndIdentifier", String (ByteOrder::swapIfLittleEndian (sustainLoop.endIdentifier)));
86 values.emplace ("Loop1Type", String (ByteOrder::swapIfLittleEndian (releaseLoop.type)));
87 values.emplace ("Loop1StartIdentifier", String (ByteOrder::swapIfLittleEndian (releaseLoop.startIdentifier)));
88 values.emplace ("Loop1EndIdentifier", String (ByteOrder::swapIfLittleEndian (releaseLoop.endIdentifier)));
89 }
90
91 static uint16 getValue16 (const StringPairArray& values, const char* name, const char* def)
92 {
94 }
95
96 static int8 getValue8 (const StringPairArray& values, const char* name, const char* def)
97 {
98 return (int8) values.getValue (name, def).getIntValue();
99 }
100
101 static void create (MemoryBlock& block, const StringPairArray& values)
102 {
103 if (values.getAllKeys().contains ("MidiUnityNote", true))
104 {
105 block.setSize ((sizeof (InstChunk) + 3) & ~(size_t) 3, true);
106 auto& inst = *static_cast<InstChunk*> (block.getData());
107
108 inst.baseNote = getValue8 (values, "MidiUnityNote", "60");
109 inst.detune = getValue8 (values, "Detune", "0");
110 inst.lowNote = getValue8 (values, "LowNote", "0");
111 inst.highNote = getValue8 (values, "HighNote", "127");
112 inst.lowVelocity = getValue8 (values, "LowVelocity", "1");
113 inst.highVelocity = getValue8 (values, "HighVelocity", "127");
114 inst.gain = (int16) getValue16 (values, "Gain", "0");
115
116 inst.sustainLoop.type = getValue16 (values, "Loop0Type", "0");
117 inst.sustainLoop.startIdentifier = getValue16 (values, "Loop0StartIdentifier", "0");
118 inst.sustainLoop.endIdentifier = getValue16 (values, "Loop0EndIdentifier", "0");
119 inst.releaseLoop.type = getValue16 (values, "Loop1Type", "0");
120 inst.releaseLoop.startIdentifier = getValue16 (values, "Loop1StartIdentifier", "0");
121 inst.releaseLoop.endIdentifier = getValue16 (values, "Loop1EndIdentifier", "0");
122 }
123 }
124
126
127 //==============================================================================
129 {
130 enum Key
131 {
132 minor = 1,
133 major = 2,
136 };
137
139 {
140 zerostruct (*this);
141
142 flags = (uint32) input.readIntBigEndian();
143 numBeats = (uint32) input.readIntBigEndian();
145 key = (uint16) input.readShortBigEndian();
149 input.read (unknown, sizeof (unknown));
150 }
151
152 void addToMetadata (std::map<String, String>& metadata) const
153 {
154 const bool rootNoteSet = rootNote != 0;
155
157 setBoolFlag (metadata, AiffAudioFormat::appleRootSet, rootNoteSet);
158
159 if (rootNoteSet)
160 metadata.emplace (AiffAudioFormat::appleRootNote, String (rootNote));
161
162 metadata.emplace (AiffAudioFormat::appleBeats, String (numBeats));
165
166 const char* keyString = nullptr;
167
168 switch (key)
169 {
170 case minor: keyString = "minor"; break;
171 case major: keyString = "major"; break;
172 case neither: keyString = "neither"; break;
173 case both: keyString = "both"; break;
174 default: break;
175 }
176
177 if (keyString != nullptr)
178 metadata.emplace (AiffAudioFormat::appleKey, keyString);
179 }
180
181 void setBoolFlag (std::map<String, String>& values,
182 const char* name,
183 bool shouldBeSet) const
184 {
185 values.emplace (name, shouldBeSet ? "1" : "0");
186 }
187
196 } JUCE_PACKED;
197
198 #if JUCE_MSVC
199 #pragma pack (pop)
200 #endif
201
202 //==============================================================================
203 namespace CATEChunk
204 {
205 static bool isValidTag (const char* d) noexcept
206 {
210 }
211
212 static bool isAppleGenre (const String& tag) noexcept
213 {
214 static const char* appleGenres[] =
215 {
216 "Rock/Blues",
217 "Electronic/Dance",
218 "Jazz",
219 "Urban",
220 "World/Ethnic",
221 "Cinematic/New Age",
222 "Orchestral",
223 "Country/Folk",
224 "Experimental",
225 "Other Genre"
226 };
227
228 for (int i = 0; i < numElementsInArray (appleGenres); ++i)
229 if (tag == appleGenres[i])
230 return true;
231
232 return false;
233 }
234
235 static String read (InputStream& input, const uint32 length)
236 {
237 MemoryBlock mb;
238 input.skipNextBytes (4);
239 input.readIntoMemoryBlock (mb, (ssize_t) length - 4);
240
241 StringArray tagsArray;
242
243 auto* data = static_cast<const char*> (mb.getData());
244 auto* dataEnd = data + mb.getSize();
245
246 while (data < dataEnd)
247 {
248 bool isGenre = false;
249
250 if (isValidTag (data))
251 {
252 auto tag = String (CharPointer_UTF8 (data), CharPointer_UTF8 (dataEnd));
253 isGenre = isAppleGenre (tag);
254 tagsArray.add (tag);
255 }
256
257 data += isGenre ? 118 : 50;
258
259 if (data < dataEnd && data[0] == 0)
260 {
261 if (data + 52 < dataEnd && isValidTag (data + 50)) data += 50;
262 else if (data + 120 < dataEnd && isValidTag (data + 118)) data += 118;
263 else if (data + 170 < dataEnd && isValidTag (data + 168)) data += 168;
264 }
265 }
266
267 return tagsArray.joinIntoString (";");
268 }
269 }
270
271 //==============================================================================
272 namespace MarkChunk
273 {
275 {
276 // (zero cue identifiers are valid for WAV but not for AIFF)
277 const String cueString ("Cue");
278 const String noteString ("CueNote");
279 const String identifierString ("Identifier");
280
281 for (auto& key : values.getAllKeys())
282 {
283 if (key.startsWith (noteString))
284 continue; // zero identifier IS valid in a COMT chunk
285
286 if (key.startsWith (cueString) && key.contains (identifierString))
287 if (values.getValue (key, "-1").getIntValue() == 0)
288 return true;
289 }
290
291 return false;
292 }
293
294 static void create (MemoryBlock& block, const StringPairArray& values)
295 {
296 auto numCues = values.getValue ("NumCuePoints", "0").getIntValue();
297
298 if (numCues > 0)
299 {
300 MemoryOutputStream out (block, false);
301 out.writeShortBigEndian ((short) numCues);
302
303 auto numCueLabels = values.getValue ("NumCueLabels", "0").getIntValue();
304 auto idOffset = metaDataContainsZeroIdentifiers (values) ? 1 : 0; // can't have zero IDs in AIFF
305
306 #if JUCE_DEBUG
307 Array<int> identifiers;
308 #endif
309
310 for (int i = 0; i < numCues; ++i)
311 {
312 auto prefixCue = "Cue" + String (i);
313 auto identifier = idOffset + values.getValue (prefixCue + "Identifier", "1").getIntValue();
314
315 #if JUCE_DEBUG
316 jassert (! identifiers.contains (identifier));
317 identifiers.add (identifier);
318 #endif
319
320 auto offset = values.getValue (prefixCue + "Offset", "0").getIntValue();
321 auto label = "CueLabel" + String (i);
322
323 for (int labelIndex = 0; labelIndex < numCueLabels; ++labelIndex)
324 {
325 auto prefixLabel = "CueLabel" + String (labelIndex);
326 auto labelIdentifier = idOffset + values.getValue (prefixLabel + "Identifier", "1").getIntValue();
327
328 if (labelIdentifier == identifier)
329 {
330 label = values.getValue (prefixLabel + "Text", label);
331 break;
332 }
333 }
334
335 out.writeShortBigEndian ((short) identifier);
336 out.writeIntBigEndian (offset);
337
338 auto labelLength = jmin ((size_t) 254, label.getNumBytesAsUTF8()); // seems to need null terminator even though it's a pstring
339 out.writeByte (static_cast<char> (labelLength + 1));
340 out.write (label.toUTF8(), labelLength);
341 out.writeByte (0);
342
343 if ((out.getDataSize() & 1) != 0)
344 out.writeByte (0);
345 }
346 }
347 }
348 }
349
350 //==============================================================================
351 namespace COMTChunk
352 {
353 static void create (MemoryBlock& block, const StringPairArray& values)
354 {
355 auto numNotes = values.getValue ("NumCueNotes", "0").getIntValue();
356
357 if (numNotes > 0)
358 {
359 MemoryOutputStream out (block, false);
360 out.writeShortBigEndian ((short) numNotes);
361
362 for (int i = 0; i < numNotes; ++i)
363 {
364 auto prefix = "CueNote" + String (i);
365
366 out.writeIntBigEndian (values.getValue (prefix + "TimeStamp", "0").getIntValue());
367 out.writeShortBigEndian ((short) values.getValue (prefix + "Identifier", "0").getIntValue());
368
369 auto comment = values.getValue (prefix + "Text", String());
370 auto commentLength = jmin (comment.getNumBytesAsUTF8(), (size_t) 65534);
371
372 out.writeShortBigEndian (static_cast<short> (commentLength + 1));
373 out.write (comment.toUTF8(), commentLength);
374 out.writeByte (0);
375
376 if ((out.getDataSize() & 1) != 0)
377 out.writeByte (0);
378 }
379 }
380 }
381 }
382}
383
384//==============================================================================
386{
387public:
390 {
391 using namespace AiffFileHelpers;
392
393 std::map<String, String> metadataValuesMap;
394
395 for (int i = 0; i != metadataValues.size(); ++i)
396 {
397 metadataValuesMap.emplace (metadataValues.getAllKeys().getReference (i),
398 metadataValues.getAllValues().getReference (i));
399 }
400
401 // If this fails, there were duplicate keys in the metadata
402 jassert ((size_t) metadataValuesMap.size() == (size_t) metadataValues.size());
403
404 if (input->readInt() == chunkName ("FORM"))
405 {
406 auto len = input->readIntBigEndian();
407 auto end = input->getPosition() + len;
408 auto nextType = input->readInt();
409
410 if (nextType == chunkName ("AIFF") || nextType == chunkName ("AIFC"))
411 {
412 bool hasGotVer = false;
413 bool hasGotData = false;
414 bool hasGotType = false;
415
416 while (input->getPosition() < end)
417 {
418 auto type = input->readInt();
419 auto length = (uint32) input->readIntBigEndian();
420 auto chunkEnd = input->getPosition() + length;
421
422 if (type == chunkName ("FVER"))
423 {
424 hasGotVer = true;
425 auto ver = input->readIntBigEndian();
426
427 if (ver != 0 && ver != (int) 0xa2805140)
428 break;
429 }
430 else if (type == chunkName ("COMM"))
431 {
432 hasGotType = true;
433
434 numChannels = (unsigned int) input->readShortBigEndian();
435 lengthInSamples = input->readIntBigEndian();
436 bitsPerSample = (unsigned int) input->readShortBigEndian();
438
439 unsigned char sampleRateBytes[10];
440 input->read (sampleRateBytes, 10);
441 const int byte0 = sampleRateBytes[0];
442
443 if ((byte0 & 0x80) != 0
444 || byte0 <= 0x3F || byte0 > 0x40
445 || (byte0 == 0x40 && sampleRateBytes[1] > 0x1C))
446 break;
447
448 auto sampRate = ByteOrder::bigEndianInt (sampleRateBytes + 2);
449 sampRate >>= (16414 - ByteOrder::bigEndianShort (sampleRateBytes));
450 sampleRate = (int) sampRate;
451
452 if (length <= 18)
453 {
454 // some types don't have a chunk large enough to include a compression
455 // type, so assume it's just big-endian pcm
456 littleEndian = false;
457 }
458 else
459 {
460 auto compType = input->readInt();
461
462 if (compType == chunkName ("NONE") || compType == chunkName ("twos"))
463 {
464 littleEndian = false;
465 }
466 else if (compType == chunkName ("sowt"))
467 {
468 littleEndian = true;
469 }
470 else if (compType == chunkName ("fl32") || compType == chunkName ("FL32"))
471 {
472 littleEndian = false;
474 }
475 else
476 {
477 sampleRate = 0;
478 break;
479 }
480 }
481 }
482 else if (type == chunkName ("SSND"))
483 {
484 hasGotData = true;
485
486 auto offset = input->readIntBigEndian();
487 dataChunkStart = input->getPosition() + 4 + offset;
489 }
490 else if (type == chunkName ("MARK"))
491 {
492 auto numCues = (uint16) input->readShortBigEndian();
493
494 // these two are always the same for AIFF-read files
495 metadataValuesMap.emplace ("NumCuePoints", String (numCues));
496 metadataValuesMap.emplace ("NumCueLabels", String (numCues));
497
498 for (uint16 i = 0; i < numCues; ++i)
499 {
500 auto identifier = (uint16) input->readShortBigEndian();
501 auto offset = (uint32) input->readIntBigEndian();
502 auto stringLength = (uint8) input->readByte();
503 MemoryBlock textBlock;
504 input->readIntoMemoryBlock (textBlock, stringLength);
505
506 // if the stringLength is even then read one more byte as the
507 // string needs to be an even number of bytes INCLUDING the
508 // leading length character in the pascal string
509 if ((stringLength & 1) == 0)
510 input->readByte();
511
512 auto prefixCue = "Cue" + String (i);
513 metadataValuesMap.emplace (prefixCue + "Identifier", String (identifier));
514 metadataValuesMap.emplace (prefixCue + "Offset", String (offset));
515
516 auto prefixLabel = "CueLabel" + String (i);
517 metadataValuesMap.emplace (prefixLabel + "Identifier", String (identifier));
518 metadataValuesMap.emplace (prefixLabel + "Text", textBlock.toString());
519 }
520 }
521 else if (type == chunkName ("COMT"))
522 {
523 auto numNotes = (uint16) input->readShortBigEndian();
524 metadataValuesMap.emplace ("NumCueNotes", String (numNotes));
525
526 for (uint16 i = 0; i < numNotes; ++i)
527 {
528 auto timestamp = (uint32) input->readIntBigEndian();
529 auto identifier = (uint16) input->readShortBigEndian(); // may be zero in this case
530 auto stringLength = (uint16) input->readShortBigEndian();
531
532 MemoryBlock textBlock;
533 input->readIntoMemoryBlock (textBlock, stringLength + (stringLength & 1));
534
535 auto prefix = "CueNote" + String (i);
536 metadataValuesMap.emplace (prefix + "TimeStamp", String (timestamp));
537 metadataValuesMap.emplace (prefix + "Identifier", String (identifier));
538 metadataValuesMap.emplace (prefix + "Text", textBlock.toString());
539 }
540 }
541 else if (type == chunkName ("INST"))
542 {
544 inst.calloc (jmax ((size_t) length + 1, sizeof (InstChunk)), 1);
545 input->read (inst, (int) length);
546 inst->copyTo (metadataValuesMap);
547 }
548 else if (type == chunkName ("basc"))
549 {
550 AiffFileHelpers::BASCChunk (*input).addToMetadata (metadataValuesMap);
551 }
552 else if (type == chunkName ("cate"))
553 {
554 metadataValuesMap.emplace (AiffAudioFormat::appleTag,
556 }
557 else if ((hasGotVer && hasGotData && hasGotType)
558 || chunkEnd < input->getPosition()
559 || input->isExhausted())
560 {
561 break;
562 }
563
564 input->setPosition (chunkEnd + (chunkEnd & 1)); // (chunks should be aligned to an even byte address)
565 }
566 }
567 }
568
569 if (metadataValuesMap.size() > 0)
570 metadataValuesMap.emplace ("MetaDataSource", "AIFF");
571
572 metadataValues.addMap (metadataValuesMap);
573 }
574
575 //==============================================================================
576 bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
577 int64 startSampleInFile, int numSamples) override
578 {
579 clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
580 startSampleInFile, numSamples, lengthInSamples);
581
582 if (numSamples <= 0)
583 return true;
584
585 input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame);
586
587 while (numSamples > 0)
588 {
589 const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3)
590 char tempBuffer [tempBufSize];
591
592 const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples);
593 const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame);
594
595 if (bytesRead < numThisTime * bytesPerFrame)
596 {
597 jassert (bytesRead >= 0);
598 zeromem (tempBuffer + bytesRead, (size_t) (numThisTime * bytesPerFrame - bytesRead));
599 }
600
601 if (littleEndian)
603 destSamples, startOffsetInDestBuffer, numDestChannels,
604 tempBuffer, (int) numChannels, numThisTime);
605 else
607 destSamples, startOffsetInDestBuffer, numDestChannels,
608 tempBuffer, (int) numChannels, numThisTime);
609
610 startOffsetInDestBuffer += numThisTime;
611 numSamples -= numThisTime;
612 }
613
614 return true;
615 }
616
617 template <typename Endianness>
618 static void copySampleData (unsigned int numBitsPerSample, bool floatingPointData,
619 int* const* destSamples, int startOffsetInDestBuffer, int numDestChannels,
620 const void* sourceData, int numberOfChannels, int numSamples) noexcept
621 {
622 switch (numBitsPerSample)
623 {
624 case 8: ReadHelper<AudioData::Int32, AudioData::Int8, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples); break;
625 case 16: ReadHelper<AudioData::Int32, AudioData::Int16, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples); break;
626 case 24: ReadHelper<AudioData::Int32, AudioData::Int24, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples); break;
627 case 32: if (floatingPointData) ReadHelper<AudioData::Float32, AudioData::Float32, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples);
628 else ReadHelper<AudioData::Int32, AudioData::Int32, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numberOfChannels, numSamples);
629 break;
630 default: jassertfalse; break;
631 }
632 }
633
637
638private:
640};
641
642//==============================================================================
644{
645public:
647 unsigned int numChans, unsigned int bits,
648 const StringPairArray& metadataValues)
649 : AudioFormatWriter (out, aiffFormatName, rate, numChans, bits)
650 {
651 using namespace AiffFileHelpers;
652
653 if (metadataValues.size() > 0)
654 {
655 // The meta data should have been sanitised for the AIFF format.
656 // If it was originally sourced from a WAV file the MetaDataSource
657 // key should be removed (or set to "AIFF") once this has been done
658 jassert (metadataValues.getValue ("MetaDataSource", "None") != "WAV");
659
660 MarkChunk::create (markChunk, metadataValues);
661 COMTChunk::create (comtChunk, metadataValues);
662 InstChunk::create (instChunk, metadataValues);
663 }
664
665 headerPosition = out->getPosition();
666 writeHeader();
667 }
668
670 {
671 if ((bytesWritten & 1) != 0)
672 output->writeByte (0);
673
674 writeHeader();
675 }
676
677 //==============================================================================
678 bool write (const int** data, int numSamples) override
679 {
680 jassert (numSamples >= 0);
681 jassert (data != nullptr && *data != nullptr); // the input must contain at least one channel!
682
683 if (writeFailed)
684 return false;
685
686 auto bytes = numChannels * (size_t) numSamples * bitsPerSample / 8;
687 tempBlock.ensureSize (bytes, false);
688
689 switch (bitsPerSample)
690 {
695 default: jassertfalse; break;
696 }
697
698 if (bytesWritten + bytes >= (size_t) 0xfff00000
699 || ! output->write (tempBlock.getData(), bytes))
700 {
701 // failed to write to disk, so let's try writing the header.
702 // If it's just run out of disk space, then if it does manage
703 // to write the header, we'll still have a useable file..
704 writeHeader();
705 writeFailed = true;
706 return false;
707 }
708
709 bytesWritten += bytes;
710 lengthInSamples += (uint64) numSamples;
711 return true;
712 }
713
714private:
718 bool writeFailed = false;
719
721 {
722 using namespace AiffFileHelpers;
723
724 const bool couldSeekOk = output->setPosition (headerPosition);
725 ignoreUnused (couldSeekOk);
726
727 // if this fails, you've given it an output stream that can't seek! It needs
728 // to be able to seek back to write the header
729 jassert (couldSeekOk);
730
731 auto headerLen = (int) (54 + (markChunk.isEmpty() ? 0 : markChunk.getSize() + 8)
732 + (comtChunk.isEmpty() ? 0 : comtChunk.getSize() + 8)
733 + (instChunk.isEmpty() ? 0 : instChunk.getSize() + 8));
734 auto audioBytes = (int) (lengthInSamples * ((bitsPerSample * numChannels) / 8));
735 audioBytes += (audioBytes & 1);
736
737 output->writeInt (chunkName ("FORM"));
738 output->writeIntBigEndian (headerLen + audioBytes - 8);
739 output->writeInt (chunkName ("AIFF"));
740 output->writeInt (chunkName ("COMM"));
741 output->writeIntBigEndian (18);
742 output->writeShortBigEndian ((short) numChannels);
743 output->writeIntBigEndian ((int) lengthInSamples);
744 output->writeShortBigEndian ((short) bitsPerSample);
745
746 uint8 sampleRateBytes[10] = {};
747
748 if (sampleRate <= 1)
749 {
750 sampleRateBytes[0] = 0x3f;
751 sampleRateBytes[1] = 0xff;
752 sampleRateBytes[2] = 0x80;
753 }
754 else
755 {
756 int mask = 0x40000000;
757 sampleRateBytes[0] = 0x40;
758
759 if (sampleRate >= mask)
760 {
762 sampleRateBytes[1] = 0x1d;
763 }
764 else
765 {
766 int n = (int) sampleRate;
767 int i;
768
769 for (i = 0; i <= 32 ; ++i)
770 {
771 if ((n & mask) != 0)
772 break;
773
774 mask >>= 1;
775 }
776
777 n = n << (i + 1);
778
779 sampleRateBytes[1] = (uint8) (29 - i);
780 sampleRateBytes[2] = (uint8) ((n >> 24) & 0xff);
781 sampleRateBytes[3] = (uint8) ((n >> 16) & 0xff);
782 sampleRateBytes[4] = (uint8) ((n >> 8) & 0xff);
783 sampleRateBytes[5] = (uint8) (n & 0xff);
784 }
785 }
786
787 output->write (sampleRateBytes, 10);
788
789 if (! markChunk.isEmpty())
790 {
791 output->writeInt (chunkName ("MARK"));
792 output->writeIntBigEndian ((int) markChunk.getSize());
793 *output << markChunk;
794 }
795
796 if (! comtChunk.isEmpty())
797 {
798 output->writeInt (chunkName ("COMT"));
799 output->writeIntBigEndian ((int) comtChunk.getSize());
800 *output << comtChunk;
801 }
802
803 if (! instChunk.isEmpty())
804 {
805 output->writeInt (chunkName ("INST"));
806 output->writeIntBigEndian ((int) instChunk.getSize());
807 *output << instChunk;
808 }
809
810 output->writeInt (chunkName ("SSND"));
811 output->writeIntBigEndian (audioBytes + 8);
812 output->writeInt (0);
813 output->writeInt (0);
814
815 jassert (output->getPosition() == headerLen);
816 }
817
819};
820
821//==============================================================================
823{
824public:
827 reader.bytesPerFrame * reader.lengthInSamples, reader.bytesPerFrame),
829 {
830 }
831
832 bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
833 int64 startSampleInFile, int numSamples) override
834 {
835 clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
836 startSampleInFile, numSamples, lengthInSamples);
837
838 if (map == nullptr || ! mappedSection.contains (Range<int64> (startSampleInFile, startSampleInFile + numSamples)))
839 {
840 jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read.
841 return false;
842 }
843
844 if (littleEndian)
846 (bitsPerSample, usesFloatingPointData, destSamples, startOffsetInDestBuffer,
847 numDestChannels, sampleToPointer (startSampleInFile), (int) numChannels, numSamples);
848 else
850 (bitsPerSample, usesFloatingPointData, destSamples, startOffsetInDestBuffer,
851 numDestChannels, sampleToPointer (startSampleInFile), (int) numChannels, numSamples);
852
853 return true;
854 }
855
856 void getSample (int64 sample, float* result) const noexcept override
857 {
858 auto num = (int) numChannels;
859
860 if (map == nullptr || ! mappedSection.contains (sample))
861 {
862 jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read.
863
864 zeromem (result, (size_t) num * sizeof (float));
865 return;
866 }
867
868 float** dest = &result;
869 const void* source = sampleToPointer (sample);
870
871 if (littleEndian)
872 {
873 switch (bitsPerSample)
874 {
880 break;
881 default: jassertfalse; break;
882 }
883 }
884 else
885 {
886 switch (bitsPerSample)
887 {
889 case 16: ReadHelper<AudioData::Float32, AudioData::Int16, AudioData::BigEndian>::read (dest, 0, 1, source, 1, num); break;
890 case 24: ReadHelper<AudioData::Float32, AudioData::Int24, AudioData::BigEndian>::read (dest, 0, 1, source, 1, num); break;
893 break;
894 default: jassertfalse; break;
895 }
896 }
897 }
898
899 void readMaxLevels (int64 startSampleInFile, int64 numSamples, Range<float>* results, int numChannelsToRead) override
900 {
901 numSamples = jmin (numSamples, lengthInSamples - startSampleInFile);
902
903 if (map == nullptr || numSamples <= 0 || ! mappedSection.contains (Range<int64> (startSampleInFile, startSampleInFile + numSamples)))
904 {
905 jassert (numSamples <= 0); // you must make sure that the window contains all the samples you're going to attempt to read.
906
907 for (int i = 0; i < numChannelsToRead; ++i)
908 results[i] = Range<float>();
909
910 return;
911 }
912
913 switch (bitsPerSample)
914 {
915 case 8: scanMinAndMax<AudioData::UInt8> (startSampleInFile, numSamples, results, numChannelsToRead); break;
916 case 16: scanMinAndMax<AudioData::Int16> (startSampleInFile, numSamples, results, numChannelsToRead); break;
917 case 24: scanMinAndMax<AudioData::Int24> (startSampleInFile, numSamples, results, numChannelsToRead); break;
918 case 32: if (usesFloatingPointData) scanMinAndMax<AudioData::Float32> (startSampleInFile, numSamples, results, numChannelsToRead);
919 else scanMinAndMax<AudioData::Int32> (startSampleInFile, numSamples, results, numChannelsToRead);
920 break;
921 default: jassertfalse; break;
922 }
923 }
924
926
927private:
928 const bool littleEndian;
929
930 template <typename SampleType>
931 void scanMinAndMax (int64 startSampleInFile, int64 numSamples, Range<float>* results, int numChannelsToRead) const noexcept
932 {
933 for (int i = 0; i < numChannelsToRead; ++i)
934 results[i] = scanMinAndMaxForChannel<SampleType> (i, startSampleInFile, numSamples);
935 }
936
937 template <typename SampleType>
938 Range<float> scanMinAndMaxForChannel (int channel, int64 startSampleInFile, int64 numSamples) const noexcept
939 {
940 return littleEndian ? scanMinAndMaxInterleaved<SampleType, AudioData::LittleEndian> (channel, startSampleInFile, numSamples)
941 : scanMinAndMaxInterleaved<SampleType, AudioData::BigEndian> (channel, startSampleInFile, numSamples);
942 }
943
945};
946
947//==============================================================================
950
952{
953 return { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000 };
954}
955
957{
958 return { 8, 16, 24 };
959}
960
961bool AiffAudioFormat::canDoStereo() { return true; }
962bool AiffAudioFormat::canDoMono() { return true; }
963
964#if JUCE_MAC
966{
968 return true;
969
970 auto type = f.getMacOSType();
971
972 // (NB: written as hex to avoid four-char-constant warnings)
973 return type == 0x41494646 /* AIFF */ || type == 0x41494643 /* AIFC */
974 || type == 0x61696666 /* aiff */ || type == 0x61696663 /* aifc */;
975}
976#endif
977
978AudioFormatReader* AiffAudioFormat::createReaderFor (InputStream* sourceStream, bool deleteStreamIfOpeningFails)
979{
980 std::unique_ptr<AiffAudioFormatReader> w (new AiffAudioFormatReader (sourceStream));
981
982 if (w->sampleRate > 0 && w->numChannels > 0)
983 return w.release();
984
985 if (! deleteStreamIfOpeningFails)
986 w->input = nullptr;
987
988 return nullptr;
989}
990
995
997{
998 if (fin != nullptr)
999 {
1000 AiffAudioFormatReader reader (fin);
1001
1002 if (reader.lengthInSamples > 0)
1003 return new MemoryMappedAiffReader (fin->getFile(), reader);
1004 }
1005
1006 return nullptr;
1007}
1008
1010 double sampleRate,
1011 unsigned int numberOfChannels,
1012 int bitsPerSample,
1013 const StringPairArray& metadataValues,
1014 int /*qualityOptionIndex*/)
1015{
1016 if (out != nullptr && getPossibleBitDepths().contains (bitsPerSample))
1017 return new AiffAudioFormatWriter (out, sampleRate, numberOfChannels,
1018 (unsigned int) bitsPerSample, metadataValues);
1019
1020 return nullptr;
1021}
1022
1023} // namespace juce
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
static const unsigned long mask[]
Definition bitwise.c:31
static uint32 littleEndianInt(const void *bytes) noexcept
Definition ByteOrder.h:236
static uint16 swapIfLittleEndian(uint16 value) noexcept
Definition ByteOrder.h:227
static uint16 bigEndianShort(const void *bytes) noexcept
Definition ByteOrder.h:241
static uint32 bigEndianInt(const void *bytes) noexcept
Definition ByteOrder.h:239
static const char *const appleDenominator
Definition juce_AiffAudioFormat.h:57
AiffAudioFormat()
Definition juce_AiffAudioFormat.cpp:948
bool canDoStereo() override
Definition juce_AiffAudioFormat.cpp:961
static const char *const appleOneShot
Definition juce_AiffAudioFormat.h:49
AudioFormatReader * createReaderFor(InputStream *sourceStream, bool deleteStreamIfOpeningFails) override
Definition juce_AiffAudioFormat.cpp:978
Array< int > getPossibleBitDepths() override
Definition juce_AiffAudioFormat.cpp:956
static const char *const appleNumerator
Definition juce_AiffAudioFormat.h:59
static const char *const appleTag
Definition juce_AiffAudioFormat.h:61
static const char *const appleBeats
Definition juce_AiffAudioFormat.h:55
bool canDoMono() override
Definition juce_AiffAudioFormat.cpp:962
Array< int > getPossibleSampleRates() override
Definition juce_AiffAudioFormat.cpp:951
static const char *const appleRootSet
Definition juce_AiffAudioFormat.h:51
MemoryMappedAudioFormatReader * createMemoryMappedReader(const File &) override
Definition juce_AiffAudioFormat.cpp:991
AudioFormatWriter * createWriterFor(OutputStream *streamToWriteTo, double sampleRateToUse, unsigned int numberOfChannels, int bitsPerSample, const StringPairArray &metadataValues, int qualityOptionIndex) override
Definition juce_AiffAudioFormat.cpp:1009
static const char *const appleKey
Definition juce_AiffAudioFormat.h:63
static const char *const appleRootNote
Definition juce_AiffAudioFormat.h:53
~AiffAudioFormat() override
Definition juce_AiffAudioFormat.cpp:949
Definition juce_AiffAudioFormat.cpp:386
AiffAudioFormatReader(InputStream *in)
Definition juce_AiffAudioFormat.cpp:388
int bytesPerFrame
Definition juce_AiffAudioFormat.cpp:634
int64 dataChunkStart
Definition juce_AiffAudioFormat.cpp:635
static void copySampleData(unsigned int numBitsPerSample, bool floatingPointData, int *const *destSamples, int startOffsetInDestBuffer, int numDestChannels, const void *sourceData, int numberOfChannels, int numSamples) noexcept
Definition juce_AiffAudioFormat.cpp:618
bool readSamples(int **destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
Definition juce_AiffAudioFormat.cpp:576
bool littleEndian
Definition juce_AiffAudioFormat.cpp:636
Definition juce_AiffAudioFormat.cpp:644
int64 headerPosition
Definition juce_AiffAudioFormat.cpp:717
MemoryBlock markChunk
Definition juce_AiffAudioFormat.cpp:715
MemoryBlock instChunk
Definition juce_AiffAudioFormat.cpp:715
bool writeFailed
Definition juce_AiffAudioFormat.cpp:718
MemoryBlock comtChunk
Definition juce_AiffAudioFormat.cpp:715
uint64 bytesWritten
Definition juce_AiffAudioFormat.cpp:716
MemoryBlock tempBlock
Definition juce_AiffAudioFormat.cpp:715
uint64 lengthInSamples
Definition juce_AiffAudioFormat.cpp:716
~AiffAudioFormatWriter() override
Definition juce_AiffAudioFormat.cpp:669
void writeHeader()
Definition juce_AiffAudioFormat.cpp:720
AiffAudioFormatWriter(OutputStream *out, double rate, unsigned int numChans, unsigned int bits, const StringPairArray &metadataValues)
Definition juce_AiffAudioFormat.cpp:646
bool write(const int **data, int numSamples) override
Definition juce_AiffAudioFormat.cpp:678
Definition juce_Array.h:56
void add(const ElementType &newElement)
Definition juce_Array.h:418
bool contains(ParameterType elementToLookFor) const
Definition juce_Array.h:400
virtual bool canHandleFile(const File &fileToTest)
Definition juce_AudioFormat.cpp:43
AudioFormat(String formatName, StringArray fileExtensions)
Definition juce_AudioFormat.cpp:29
Definition juce_AudioFormatReader.h:44
InputStream * input
Definition juce_AudioFormatReader.h:248
bool usesFloatingPointData
Definition juce_AudioFormatReader.h:237
StringPairArray metadataValues
Definition juce_AudioFormatReader.h:245
static void clearSamplesBeyondAvailableLength(int **destChannels, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int &numSamples, int64 fileLengthInSamples)
Definition juce_AudioFormatReader.h:309
int64 lengthInSamples
Definition juce_AudioFormatReader.h:231
double sampleRate
Definition juce_AudioFormatReader.h:225
AudioFormatReader(InputStream *sourceStream, const String &formatName)
Definition juce_AudioFormatReader.cpp:29
unsigned int bitsPerSample
Definition juce_AudioFormatReader.h:228
virtual void readMaxLevels(int64 startSample, int64 numSamples, Range< float > *results, int numChannelsToRead)
Definition juce_AudioFormatReader.cpp:209
unsigned int numChannels
Definition juce_AudioFormatReader.h:234
Definition juce_AudioFormatWriter.h:44
unsigned int numChannels
Definition juce_AudioFormatWriter.h:251
double sampleRate
Definition juce_AudioFormatWriter.h:248
unsigned int bitsPerSample
Definition juce_AudioFormatWriter.h:254
AudioFormatWriter(OutputStream *destStream, const String &formatName, double sampleRate, unsigned int numberOfChannels, unsigned int bitsPerSample)
Definition juce_AudioFormatWriter.cpp:29
OutputStream * output
Definition juce_AudioFormatWriter.h:263
static Type swapIfLittleEndian(Type value) noexcept
Definition juce_ByteOrder.h:78
Definition juce_CharPointer_UTF8.h:35
static bool isLowerCase(juce_wchar character) noexcept
Definition juce_CharacterFunctions.cpp:47
static bool isLetterOrDigit(char character) noexcept
Definition juce_CharacterFunctions.cpp:90
static bool isUpperCase(juce_wchar character) noexcept
Definition juce_CharacterFunctions.cpp:38
Definition juce_File.h:45
Definition juce_FileInputStream.h:35
const File & getFile() const noexcept
Definition juce_FileInputStream.h:51
Definition juce_HeapBlock.h:87
void calloc(SizeType newNumElements, const size_t elementSize=sizeof(ElementType))
Definition juce_HeapBlock.h:263
Definition juce_InputStream.h:37
virtual int readIntBigEndian()
Definition juce_InputStream.cpp:98
virtual void skipNextBytes(int64 numBytesToSkip)
Definition juce_InputStream.cpp:237
virtual short readShortBigEndian()
Definition juce_InputStream.cpp:78
virtual size_t readIntoMemoryBlock(MemoryBlock &destBlock, ssize_t maxNumBytesToRead=-1)
Definition juce_InputStream.cpp:223
virtual int read(void *destBuffer, int maxBytesToRead)=0
Definition juce_MemoryBlock.h:33
void * getData() noexcept
Definition juce_MemoryBlock.h:91
void setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
Definition juce_MemoryBlock.cpp:115
String toString() const
Definition juce_MemoryBlock.cpp:265
size_t getSize() const noexcept
Definition juce_MemoryBlock.h:127
Definition juce_AiffAudioFormat.cpp:823
void scanMinAndMax(int64 startSampleInFile, int64 numSamples, Range< float > *results, int numChannelsToRead) const noexcept
Definition juce_AiffAudioFormat.cpp:931
MemoryMappedAiffReader(const File &f, const AiffAudioFormatReader &reader)
Definition juce_AiffAudioFormat.cpp:825
Range< float > scanMinAndMaxForChannel(int channel, int64 startSampleInFile, int64 numSamples) const noexcept
Definition juce_AiffAudioFormat.cpp:938
const bool littleEndian
Definition juce_AiffAudioFormat.cpp:928
void readMaxLevels(int64 startSampleInFile, int64 numSamples, Range< float > *results, int numChannelsToRead) override
Definition juce_AiffAudioFormat.cpp:899
bool readSamples(int **destSamples, int numDestChannels, int startOffsetInDestBuffer, int64 startSampleInFile, int numSamples) override
Definition juce_AiffAudioFormat.cpp:832
void getSample(int64 sample, float *result) const noexcept override
Definition juce_AiffAudioFormat.cpp:856
Definition juce_MemoryMappedAudioFormatReader.h:47
MemoryMappedAudioFormatReader(const File &file, const AudioFormatReader &details, int64 dataChunkStart, int64 dataChunkLength, int bytesPerFrame)
Definition juce_AudioFormatReader.cpp:404
Range< int64 > mappedSection
Definition juce_MemoryMappedAudioFormatReader.h:86
std::unique_ptr< MemoryMappedFile > map
Definition juce_MemoryMappedAudioFormatReader.h:87
int64 dataChunkStart
Definition juce_MemoryMappedAudioFormatReader.h:88
int bytesPerFrame
Definition juce_MemoryMappedAudioFormatReader.h:89
const void * sampleToPointer(int64 sample) const noexcept
Definition juce_MemoryMappedAudioFormatReader.h:98
Range< float > scanMinAndMaxInterleaved(int channel, int64 startSampleInFile, int64 numSamples) const noexcept
Definition juce_MemoryMappedAudioFormatReader.h:102
Definition juce_MemoryOutputStream.h:36
Definition juce_OutputStream.h:38
Definition juce_Range.h:40
Definition juce_StringArray.h:35
String joinIntoString(StringRef separatorString, int startIndex=0, int numberOfElements=-1) const
Definition juce_StringArray.cpp:289
bool contains(StringRef stringToLookFor, bool ignoreCase=false) const
Definition juce_StringArray.cpp:189
void add(String stringToAdd)
Definition juce_StringArray.cpp:136
Definition juce_String.h:53
int getIntValue() const noexcept
Definition juce_String.cpp:1871
Definition juce_StringPairArray.h:35
String getValue(StringRef, const String &defaultReturnValue) const
Definition juce_StringPairArray.cpp:86
int size() const noexcept
Definition juce_StringPairArray.h:93
const StringArray & getAllKeys() const noexcept
Definition juce_StringPairArray.h:87
UINT_D64 w
Definition inflate.c:942
unsigned d
Definition inflate.c:940
register unsigned i
Definition inflate.c:1575
unsigned f
Definition inflate.c:1572
static const char * name
Definition pugl.h:1582
JSAMPIMAGE data
Definition jpeglib.h:945
#define jassert(expression)
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
#define jassertfalse
float in
Definition lilv_test.c:1460
float out
Definition lilv_test.c:1461
Definition juce_AiffAudioFormat.cpp:204
static String read(InputStream &input, const uint32 length)
Definition juce_AiffAudioFormat.cpp:235
static bool isAppleGenre(const String &tag) noexcept
Definition juce_AiffAudioFormat.cpp:212
static bool isValidTag(const char *d) noexcept
Definition juce_AiffAudioFormat.cpp:205
Definition juce_AiffAudioFormat.cpp:352
static void create(MemoryBlock &block, const StringPairArray &values)
Definition juce_AiffAudioFormat.cpp:353
Definition juce_AiffAudioFormat.cpp:273
static void create(MemoryBlock &block, const StringPairArray &values)
Definition juce_AiffAudioFormat.cpp:294
static bool metaDataContainsZeroIdentifiers(const StringPairArray &values)
Definition juce_AiffAudioFormat.cpp:274
Definition juce_AiffAudioFormat.cpp:43
int chunkName(const char *name) noexcept
Definition juce_AiffAudioFormat.cpp:44
struct juce::AiffFileHelpers::InstChunk JUCE_PACKED
Definition carla_juce.cpp:31
void zerostruct(Type &structure) noexcept
Definition juce_Memory.h:32
unsigned short uint16
Definition juce_MathsFunctions.h:41
unsigned long long uint64
Definition juce_MathsFunctions.h:56
constexpr Type jmin(Type a, Type b)
Definition juce_MathsFunctions.h:106
class JUCE_API juce::PixelARGB JUCE_PACKED
unsigned int uint32
Definition juce_MathsFunctions.h:45
constexpr Type jmax(Type a, Type b)
Definition juce_MathsFunctions.h:94
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Definition juce_RangedDirectoryIterator.h:184
static const char *const aiffFormatName
Definition juce_AiffAudioFormat.cpp:29
signed short int16
Definition juce_MathsFunctions.h:39
long long int64
Definition juce_MathsFunctions.h:54
wchar_t juce_wchar
Definition juce_CharacterFunctions.h:42
void ignoreUnused(Types &&...) noexcept
Definition juce_MathsFunctions.h:333
signed char int8
Definition juce_MathsFunctions.h:35
unsigned char uint8
Definition juce_MathsFunctions.h:37
@ label
Definition juce_AccessibilityRole.h:44
constexpr int numElementsInArray(Type(&)[N]) noexcept
Definition juce_MathsFunctions.h:344
void zeromem(void *memory, size_t numBytes) noexcept
Definition juce_Memory.h:28
png_uint_32 length
Definition png.c:2247
Definition juce_AiffAudioFormat.cpp:129
uint16 key
Definition juce_AiffAudioFormat.cpp:191
BASCChunk(InputStream &input)
Definition juce_AiffAudioFormat.cpp:138
uint16 timeSigNum
Definition juce_AiffAudioFormat.cpp:192
uint16 rootNote
Definition juce_AiffAudioFormat.cpp:190
Key
Definition juce_AiffAudioFormat.cpp:131
@ minor
Definition juce_AiffAudioFormat.cpp:132
@ neither
Definition juce_AiffAudioFormat.cpp:134
@ both
Definition juce_AiffAudioFormat.cpp:135
@ major
Definition juce_AiffAudioFormat.cpp:133
void setBoolFlag(std::map< String, String > &values, const char *name, bool shouldBeSet) const
Definition juce_AiffAudioFormat.cpp:181
uint32 flags
Definition juce_AiffAudioFormat.cpp:188
uint16 oneShot
Definition juce_AiffAudioFormat.cpp:194
void addToMetadata(std::map< String, String > &metadata) const
Definition juce_AiffAudioFormat.cpp:152
uint8 unknown[66]
Definition juce_AiffAudioFormat.cpp:195
uint32 numBeats
Definition juce_AiffAudioFormat.cpp:189
uint16 timeSigDen
Definition juce_AiffAudioFormat.cpp:193
Definition juce_AiffAudioFormat.cpp:54
uint16 startIdentifier
Definition juce_AiffAudioFormat.cpp:56
uint16 endIdentifier
Definition juce_AiffAudioFormat.cpp:57
uint16 type
Definition juce_AiffAudioFormat.cpp:55
Definition juce_AiffAudioFormat.cpp:52
Loop releaseLoop
Definition juce_AiffAudioFormat.cpp:68
int8 baseNote
Definition juce_AiffAudioFormat.cpp:60
int8 highVelocity
Definition juce_AiffAudioFormat.cpp:65
int8 lowVelocity
Definition juce_AiffAudioFormat.cpp:64
int16 gain
Definition juce_AiffAudioFormat.cpp:66
static void create(MemoryBlock &block, const StringPairArray &values)
Definition juce_AiffAudioFormat.cpp:101
int8 highNote
Definition juce_AiffAudioFormat.cpp:63
int8 lowNote
Definition juce_AiffAudioFormat.cpp:62
static int8 getValue8(const StringPairArray &values, const char *name, const char *def)
Definition juce_AiffAudioFormat.cpp:96
void copyTo(std::map< String, String > &values) const
Definition juce_AiffAudioFormat.cpp:70
int8 detune
Definition juce_AiffAudioFormat.cpp:61
static uint16 getValue16(const StringPairArray &values, const char *name, const char *def)
Definition juce_AiffAudioFormat.cpp:91
Loop sustainLoop
Definition juce_AiffAudioFormat.cpp:67
Definition juce_AudioFormatReader.h:282
Definition juce_AudioFormatWriter.h:268
signed int sample
Definition tap_dynamics_m.c:41
int n
Definition crypt.c:458
ZCONST char * key
Definition crypt.c:587
int result
Definition process.c:1455
read(f, &c, 1)
typedef int(UZ_EXP MsgFn)()
struct zdirent * file
Definition win32.c:1500