Browse Source

Add radium-compressor

master
falkTX 10 years ago
parent
commit
2d11ea5c0d
100 changed files with 34167 additions and 0 deletions
  1. +8
    -0
      ports/Makefile
  2. +12
    -0
      ports/radium-compressor/JuceLibraryCode/ReadMe.txt
  3. +601
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp
  4. +644
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h
  5. +560
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp
  6. +444
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h
  7. +104
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h
  8. +252
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.cpp
  9. +149
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.h
  10. +321
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Reverb.h
  11. +63
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.cpp
  12. +100
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h
  13. +26
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.mm
  14. +21
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/juce_module_info
  15. +290
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp
  16. +241
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h
  17. +425
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.cpp
  18. +187
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.h
  19. +184
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp
  20. +209
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h
  21. +1049
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  22. +940
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.h
  23. +335
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp
  24. +281
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h
  25. +184
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_AudioSource.h
  26. +262
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp
  27. +114
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.h
  28. +186
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.cpp
  29. +149
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.h
  30. +72
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp
  31. +71
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h
  32. +158
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp
  33. +104
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.h
  34. +81
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_PositionableAudioSource.h
  35. +254
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp
  36. +106
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h
  37. +81
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp
  38. +80
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.h
  39. +77
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp
  40. +76
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.h
  41. +433
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  42. +494
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h
  43. +170
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDBurner.h
  44. +58
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.cpp
  45. +175
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.h
  46. +953
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
  47. +512
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
  48. +49
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp
  49. +333
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h
  50. +79
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.cpp
  51. +186
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h
  52. +236
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.cpp
  53. +139
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h
  54. +26
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.mm
  55. +27
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/juce_module_info
  56. +183
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiInput.h
  57. +153
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp
  58. +105
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h
  59. +163
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.cpp
  60. +148
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.h
  61. +176
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h
  62. +444
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Audio.cpp
  63. +85
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Midi.cpp
  64. +623
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp
  65. +547
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp
  66. +1011
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp
  67. +78
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_AudioCDReader.cpp
  68. +606
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
  69. +476
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_Midi.cpp
  70. +492
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDBurner.mm
  71. +260
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm
  72. +1269
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
  73. +523
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp
  74. +1580
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_ASIO.cpp
  75. +412
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDBurner.cpp
  76. +1310
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDReader.cpp
  77. +1290
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp
  78. +482
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_Midi.cpp
  79. +1226
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp
  80. +184
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp
  81. +117
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h
  82. +302
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp
  83. +187
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.h
  84. +49
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/Flac Licence.txt
  85. +402
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/all.h
  86. +212
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/alloc.h
  87. +45
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/assert.h
  88. +184
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/callback.h
  89. +91
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/export.h
  90. +1010
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/format.h
  91. +149
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitmath.c
  92. +1350
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitreader.c
  93. +880
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitwriter.c
  94. +418
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/cpu.c
  95. +142
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/crc.c
  96. +435
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/fixed.c
  97. +308
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/float.c
  98. +598
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/format.c
  99. +49
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/all.h
  100. +42
    -0
      ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitmath.h

+ 8
- 0
ports/Makefile View File

@@ -16,6 +16,8 @@ lv2:
$(MAKE) -C cabbage/LV2-midi
$(MAKE) -C protoplug/LV2-fx
$(MAKE) -C protoplug/LV2-gen
$(MAKE) -C radium-compressor/LV2-mono
$(MAKE) -C radium-compressor/LV2-stereo

# -----------------------------------------
# vst
@@ -28,6 +30,8 @@ vst:
$(MAKE) -C cabbage/VST-midi
$(MAKE) -C protoplug/VST-fx
$(MAKE) -C protoplug/VST-gen
$(MAKE) -C radium-compressor/VST-mono
$(MAKE) -C radium-compressor/VST-stereo

# -----------------------------------------
# clean
@@ -40,6 +44,8 @@ clean:
$(MAKE) clean -C cabbage/LV2-midi
$(MAKE) clean -C protoplug/LV2-fx
$(MAKE) clean -C protoplug/LV2-gen
$(MAKE) clean -C radium-compressor/LV2-mono
$(MAKE) clean -C radium-compressor/LV2-stereo

# VST
$(MAKE) clean -C argotlunar/VST
@@ -48,6 +54,8 @@ clean:
$(MAKE) clean -C cabbage/VST-midi
$(MAKE) clean -C protoplug/VST-fx
$(MAKE) clean -C protoplug/VST-gen
$(MAKE) clean -C radium-compressor/VST-mono
$(MAKE) clean -C radium-compressor/VST-stereo

rm -rf */LV2/intermediate
rm -rf */VST/intermediate


+ 12
- 0
ports/radium-compressor/JuceLibraryCode/ReadMe.txt View File

@@ -0,0 +1,12 @@
Important Note!!
================
The purpose of this folder is to contain files that are auto-generated by the Introjucer,
and ALL files in this folder will be mercilessly DELETED and completely re-written whenever
the Introjucer saves your project.
Therefore, it's a bad idea to make any manual changes to the files in here, or to
put any of your own files in here if you don't want to lose them. (Of course you may choose
to add the folder's contents to your version-control system so that you can re-merge your own
modifications after the Introjucer has saved its changes).

+ 601
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp View File

@@ -0,0 +1,601 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fff;
char* intData = static_cast <char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
for (int i = 0; i < numSamples; ++i)
{
*(uint16*) intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
intData += destBytesPerSample;
}
}
else
{
intData += destBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= destBytesPerSample;
*(uint16*) intData = ByteOrder::swapIfBigEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
}
}
}
void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fff;
char* intData = static_cast <char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
for (int i = 0; i < numSamples; ++i)
{
*(uint16*) intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
intData += destBytesPerSample;
}
}
else
{
intData += destBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= destBytesPerSample;
*(uint16*) intData = ByteOrder::swapIfLittleEndian ((uint16) (short) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
}
}
}
void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fffff;
char* intData = static_cast <char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
for (int i = 0; i < numSamples; ++i)
{
ByteOrder::littleEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
intData += destBytesPerSample;
}
}
else
{
intData += destBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= destBytesPerSample;
ByteOrder::littleEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
}
}
}
void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fffff;
char* intData = static_cast <char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
for (int i = 0; i < numSamples; ++i)
{
ByteOrder::bigEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
intData += destBytesPerSample;
}
}
else
{
intData += destBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= destBytesPerSample;
ByteOrder::bigEndian24BitToChars (roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])), intData);
}
}
}
void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fffffff;
char* intData = static_cast <char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
for (int i = 0; i < numSamples; ++i)
{
*(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
intData += destBytesPerSample;
}
}
else
{
intData += destBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= destBytesPerSample;
*(uint32*)intData = ByteOrder::swapIfBigEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
}
}
}
void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fffffff;
char* intData = static_cast <char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
for (int i = 0; i < numSamples; ++i)
{
*(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
intData += destBytesPerSample;
}
}
else
{
intData += destBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= destBytesPerSample;
*(uint32*)intData = ByteOrder::swapIfLittleEndian ((uint32) roundToInt (jlimit (-maxVal, maxVal, maxVal * source[i])));
}
}
}
void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data!
char* d = static_cast <char*> (dest);
for (int i = 0; i < numSamples; ++i)
{
*(float*) d = source[i];
#if JUCE_BIG_ENDIAN
*(uint32*) d = ByteOrder::swap (*(uint32*) d);
#endif
d += destBytesPerSample;
}
}
void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data!
char* d = static_cast <char*> (dest);
for (int i = 0; i < numSamples; ++i)
{
*(float*) d = source[i];
#if JUCE_LITTLE_ENDIAN
*(uint32*) d = ByteOrder::swap (*(uint32*) d);
#endif
d += destBytesPerSample;
}
}
//==============================================================================
void AudioDataConverters::convertInt16LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fff;
const char* intData = static_cast <const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
for (int i = 0; i < numSamples; ++i)
{
dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData);
intData += srcBytesPerSample;
}
}
else
{
intData += srcBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= srcBytesPerSample;
dest[i] = scale * (short) ByteOrder::swapIfBigEndian (*(uint16*)intData);
}
}
}
void AudioDataConverters::convertInt16BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fff;
const char* intData = static_cast <const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
for (int i = 0; i < numSamples; ++i)
{
dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData);
intData += srcBytesPerSample;
}
}
else
{
intData += srcBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= srcBytesPerSample;
dest[i] = scale * (short) ByteOrder::swapIfLittleEndian (*(uint16*)intData);
}
}
}
void AudioDataConverters::convertInt24LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fffff;
const char* intData = static_cast <const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
for (int i = 0; i < numSamples; ++i)
{
dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData);
intData += srcBytesPerSample;
}
}
else
{
intData += srcBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= srcBytesPerSample;
dest[i] = scale * (short) ByteOrder::littleEndian24Bit (intData);
}
}
}
void AudioDataConverters::convertInt24BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fffff;
const char* intData = static_cast <const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
for (int i = 0; i < numSamples; ++i)
{
dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData);
intData += srcBytesPerSample;
}
}
else
{
intData += srcBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= srcBytesPerSample;
dest[i] = scale * (short) ByteOrder::bigEndian24Bit (intData);
}
}
}
void AudioDataConverters::convertInt32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fffffff;
const char* intData = static_cast <const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
for (int i = 0; i < numSamples; ++i)
{
dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData);
intData += srcBytesPerSample;
}
}
else
{
intData += srcBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= srcBytesPerSample;
dest[i] = scale * (int) ByteOrder::swapIfBigEndian (*(uint32*) intData);
}
}
}
void AudioDataConverters::convertInt32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fffffff;
const char* intData = static_cast <const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
for (int i = 0; i < numSamples; ++i)
{
dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData);
intData += srcBytesPerSample;
}
}
else
{
intData += srcBytesPerSample * numSamples;
for (int i = numSamples; --i >= 0;)
{
intData -= srcBytesPerSample;
dest[i] = scale * (int) ByteOrder::swapIfLittleEndian (*(uint32*) intData);
}
}
}
void AudioDataConverters::convertFloat32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const char* s = static_cast <const char*> (source);
for (int i = 0; i < numSamples; ++i)
{
dest[i] = *(float*)s;
#if JUCE_BIG_ENDIAN
uint32* const d = (uint32*) (dest + i);
*d = ByteOrder::swap (*d);
#endif
s += srcBytesPerSample;
}
}
void AudioDataConverters::convertFloat32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const char* s = static_cast <const char*> (source);
for (int i = 0; i < numSamples; ++i)
{
dest[i] = *(float*)s;
#if JUCE_LITTLE_ENDIAN
uint32* const d = (uint32*) (dest + i);
*d = ByteOrder::swap (*d);
#endif
s += srcBytesPerSample;
}
}
//==============================================================================
void AudioDataConverters::convertFloatToFormat (const DataFormat destFormat,
const float* const source,
void* const dest,
const int numSamples)
{
switch (destFormat)
{
case int16LE: convertFloatToInt16LE (source, dest, numSamples); break;
case int16BE: convertFloatToInt16BE (source, dest, numSamples); break;
case int24LE: convertFloatToInt24LE (source, dest, numSamples); break;
case int24BE: convertFloatToInt24BE (source, dest, numSamples); break;
case int32LE: convertFloatToInt32LE (source, dest, numSamples); break;
case int32BE: convertFloatToInt32BE (source, dest, numSamples); break;
case float32LE: convertFloatToFloat32LE (source, dest, numSamples); break;
case float32BE: convertFloatToFloat32BE (source, dest, numSamples); break;
default: jassertfalse; break;
}
}
void AudioDataConverters::convertFormatToFloat (const DataFormat sourceFormat,
const void* const source,
float* const dest,
const int numSamples)
{
switch (sourceFormat)
{
case int16LE: convertInt16LEToFloat (source, dest, numSamples); break;
case int16BE: convertInt16BEToFloat (source, dest, numSamples); break;
case int24LE: convertInt24LEToFloat (source, dest, numSamples); break;
case int24BE: convertInt24BEToFloat (source, dest, numSamples); break;
case int32LE: convertInt32LEToFloat (source, dest, numSamples); break;
case int32BE: convertInt32BEToFloat (source, dest, numSamples); break;
case float32LE: convertFloat32LEToFloat (source, dest, numSamples); break;
case float32BE: convertFloat32BEToFloat (source, dest, numSamples); break;
default: jassertfalse; break;
}
}
//==============================================================================
void AudioDataConverters::interleaveSamples (const float** const source,
float* const dest,
const int numSamples,
const int numChannels)
{
for (int chan = 0; chan < numChannels; ++chan)
{
int i = chan;
const float* src = source [chan];
for (int j = 0; j < numSamples; ++j)
{
dest [i] = src [j];
i += numChannels;
}
}
}
void AudioDataConverters::deinterleaveSamples (const float* const source,
float** const dest,
const int numSamples,
const int numChannels)
{
for (int chan = 0; chan < numChannels; ++chan)
{
int i = chan;
float* dst = dest [chan];
for (int j = 0; j < numSamples; ++j)
{
dst [j] = source [i];
i += numChannels;
}
}
}
//==============================================================================
#if JUCE_UNIT_TESTS
class AudioConversionTests : public UnitTest
{
public:
AudioConversionTests() : UnitTest ("Audio data conversion") {}
template <class F1, class E1, class F2, class E2>
struct Test5
{
static void test (UnitTest& unitTest)
{
test (unitTest, false);
test (unitTest, true);
}
static void test (UnitTest& unitTest, bool inPlace)
{
const int numSamples = 2048;
int32 original [numSamples], converted [numSamples], reversed [numSamples];
Random r;
{
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> d (original);
bool clippingFailed = false;
for (int i = 0; i < numSamples / 2; ++i)
{
d.setAsFloat (r.nextFloat() * 2.2f - 1.1f);
if (! d.isFloatingPoint())
clippingFailed = d.getAsFloat() > 1.0f || d.getAsFloat() < -1.0f || clippingFailed;
++d;
d.setAsInt32 (r.nextInt());
++d;
}
unitTest.expect (! clippingFailed);
}
// convert data from the source to dest format..
ScopedPointer<AudioData::Converter> conv (new AudioData::ConverterInstance <AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const>,
AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::NonConst> >());
conv->convertSamples (inPlace ? reversed : converted, original, numSamples);
// ..and back again..
conv = new AudioData::ConverterInstance <AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::Const>,
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::NonConst> >();
if (! inPlace)
zeromem (reversed, sizeof (reversed));
conv->convertSamples (reversed, inPlace ? reversed : converted, numSamples);
{
int biggestDiff = 0;
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const> d1 (original);
AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const> d2 (reversed);
const int errorMargin = 2 * AudioData::Pointer<F1, E1, AudioData::NonInterleaved, AudioData::Const>::get32BitResolution()
+ AudioData::Pointer<F2, E2, AudioData::NonInterleaved, AudioData::Const>::get32BitResolution();
for (int i = 0; i < numSamples; ++i)
{
biggestDiff = jmax (biggestDiff, std::abs (d1.getAsInt32() - d2.getAsInt32()));
++d1;
++d2;
}
unitTest.expect (biggestDiff <= errorMargin);
}
}
};
template <class F1, class E1, class FormatType>
struct Test3
{
static void test (UnitTest& unitTest)
{
Test5 <F1, E1, FormatType, AudioData::BigEndian>::test (unitTest);
Test5 <F1, E1, FormatType, AudioData::LittleEndian>::test (unitTest);
}
};
template <class FormatType, class Endianness>
struct Test2
{
static void test (UnitTest& unitTest)
{
Test3 <FormatType, Endianness, AudioData::Int8>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::UInt8>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Int16>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Int24>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Int32>::test (unitTest);
Test3 <FormatType, Endianness, AudioData::Float32>::test (unitTest);
}
};
template <class FormatType>
struct Test1
{
static void test (UnitTest& unitTest)
{
Test2 <FormatType, AudioData::BigEndian>::test (unitTest);
Test2 <FormatType, AudioData::LittleEndian>::test (unitTest);
}
};
void runTest()
{
beginTest ("Round-trip conversion: Int8");
Test1 <AudioData::Int8>::test (*this);
beginTest ("Round-trip conversion: Int16");
Test1 <AudioData::Int16>::test (*this);
beginTest ("Round-trip conversion: Int24");
Test1 <AudioData::Int24>::test (*this);
beginTest ("Round-trip conversion: Int32");
Test1 <AudioData::Int32>::test (*this);
beginTest ("Round-trip conversion: Float32");
Test1 <AudioData::Float32>::test (*this);
}
};
static AudioConversionTests audioConversionUnitTests;
#endif

+ 644
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h View File

@@ -0,0 +1,644 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIODATACONVERTERS_JUCEHEADER__
#define __JUCE_AUDIODATACONVERTERS_JUCEHEADER__
//==============================================================================
/**
This class a container which holds all the classes pertaining to the AudioData::Pointer
audio sample format class.
@see AudioData::Pointer.
*/
class JUCE_API AudioData
{
public:
//==============================================================================
// These types can be used as the SampleFormat template parameter for the AudioData::Pointer class.
class Int8; /**< Used as a template parameter for AudioData::Pointer. Indicates an 8-bit integer packed data format. */
class UInt8; /**< Used as a template parameter for AudioData::Pointer. Indicates an 8-bit unsigned integer packed data format. */
class Int16; /**< Used as a template parameter for AudioData::Pointer. Indicates an 16-bit integer packed data format. */
class Int24; /**< Used as a template parameter for AudioData::Pointer. Indicates an 24-bit integer packed data format. */
class Int32; /**< Used as a template parameter for AudioData::Pointer. Indicates an 32-bit integer packed data format. */
class Float32; /**< Used as a template parameter for AudioData::Pointer. Indicates an 32-bit float data format. */
//==============================================================================
// These types can be used as the Endianness template parameter for the AudioData::Pointer class.
class BigEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in big-endian order. */
class LittleEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in little-endian order. */
class NativeEndian; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored in the CPU's native endianness. */
//==============================================================================
// These types can be used as the InterleavingType template parameter for the AudioData::Pointer class.
class NonInterleaved; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are stored contiguously. */
class Interleaved; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples are interleaved with a number of other channels. */
//==============================================================================
// These types can be used as the Constness template parameter for the AudioData::Pointer class.
class NonConst; /**< Used as a template parameter for AudioData::Pointer. Indicates that the pointer can be used for non-const data. */
class Const; /**< Used as a template parameter for AudioData::Pointer. Indicates that the samples can only be used for const data.. */
#ifndef DOXYGEN
//==============================================================================
class BigEndian
{
public:
template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatBE(); }
template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatBE (newValue); }
template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32BE(); }
template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32BE (newValue); }
template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) noexcept { dest.copyFromBE (source); }
enum { isBigEndian = 1 };
};
class LittleEndian
{
public:
template <class SampleFormatType> static inline float getAsFloat (SampleFormatType& s) noexcept { return s.getAsFloatLE(); }
template <class SampleFormatType> static inline void setAsFloat (SampleFormatType& s, float newValue) noexcept { s.setAsFloatLE (newValue); }
template <class SampleFormatType> static inline int32 getAsInt32 (SampleFormatType& s) noexcept { return s.getAsInt32LE(); }
template <class SampleFormatType> static inline void setAsInt32 (SampleFormatType& s, int32 newValue) noexcept { s.setAsInt32LE (newValue); }
template <class SourceType, class DestType> static inline void copyFrom (DestType& dest, SourceType& source) noexcept { dest.copyFromLE (source); }
enum { isBigEndian = 0 };
};
#if JUCE_BIG_ENDIAN
class NativeEndian : public BigEndian {};
#else
class NativeEndian : public LittleEndian {};
#endif
//==============================================================================
class Int8
{
public:
inline Int8 (void* d) noexcept : data (static_cast <int8*> (d)) {}
inline void advance() noexcept { ++data; }
inline void skip (int numSamples) noexcept { data += numSamples; }
inline float getAsFloatLE() const noexcept { return (float) (*data * (1.0 / (1.0 + maxValue))); }
inline float getAsFloatBE() const noexcept { return getAsFloatLE(); }
inline void setAsFloatLE (float newValue) noexcept { *data = (int8) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))); }
inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); }
inline int32 getAsInt32LE() const noexcept { return (int) (*data << 24); }
inline int32 getAsInt32BE() const noexcept { return getAsInt32LE(); }
inline void setAsInt32LE (int newValue) noexcept { *data = (int8) (newValue >> 24); }
inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); }
inline void clear() noexcept { *data = 0; }
inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int8& source) noexcept { *data = *source.data; }
int8* data;
enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 };
};
class UInt8
{
public:
inline UInt8 (void* d) noexcept : data (static_cast <uint8*> (d)) {}
inline void advance() noexcept { ++data; }
inline void skip (int numSamples) noexcept { data += numSamples; }
inline float getAsFloatLE() const noexcept { return (float) ((*data - 128) * (1.0 / (1.0 + maxValue))); }
inline float getAsFloatBE() const noexcept { return getAsFloatLE(); }
inline void setAsFloatLE (float newValue) noexcept { *data = (uint8) jlimit (0, 255, 128 + roundToInt (newValue * (1.0 + maxValue))); }
inline void setAsFloatBE (float newValue) noexcept { setAsFloatLE (newValue); }
inline int32 getAsInt32LE() const noexcept { return (int) ((*data - 128) << 24); }
inline int32 getAsInt32BE() const noexcept { return getAsInt32LE(); }
inline void setAsInt32LE (int newValue) noexcept { *data = (uint8) (128 + (newValue >> 24)); }
inline void setAsInt32BE (int newValue) noexcept { setAsInt32LE (newValue); }
inline void clear() noexcept { *data = 128; }
inline void clearMultiple (int num) noexcept { memset (data, 128, (size_t) num) ;}
template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (UInt8& source) noexcept { *data = *source.data; }
uint8* data;
enum { bytesPerSample = 1, maxValue = 0x7f, resolution = (1 << 24), isFloat = 0 };
};
class Int16
{
public:
inline Int16 (void* d) noexcept : data (static_cast <uint16*> (d)) {}
inline void advance() noexcept { ++data; }
inline void skip (int numSamples) noexcept { data += numSamples; }
inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfBigEndian (*data)); }
inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int16) ByteOrder::swapIfLittleEndian (*data)); }
inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); }
inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue)))); }
inline int32 getAsInt32LE() const noexcept { return (int32) (ByteOrder::swapIfBigEndian ((uint16) *data) << 16); }
inline int32 getAsInt32BE() const noexcept { return (int32) (ByteOrder::swapIfLittleEndian ((uint16) *data) << 16); }
inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint16) (newValue >> 16)); }
inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint16) (newValue >> 16)); }
inline void clear() noexcept { *data = 0; }
inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int16& source) noexcept { *data = *source.data; }
uint16* data;
enum { bytesPerSample = 2, maxValue = 0x7fff, resolution = (1 << 16), isFloat = 0 };
};
class Int24
{
public:
inline Int24 (void* d) noexcept : data (static_cast <char*> (d)) {}
inline void advance() noexcept { data += 3; }
inline void skip (int numSamples) noexcept { data += 3 * numSamples; }
inline float getAsFloatLE() const noexcept { return (float) (ByteOrder::littleEndian24Bit (data) * (1.0 / (1.0 + maxValue))); }
inline float getAsFloatBE() const noexcept { return (float) (ByteOrder::bigEndian24Bit (data) * (1.0 / (1.0 + maxValue))); }
inline void setAsFloatLE (float newValue) noexcept { ByteOrder::littleEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); }
inline void setAsFloatBE (float newValue) noexcept { ByteOrder::bigEndian24BitToChars (jlimit ((int) -maxValue, (int) maxValue, roundToInt (newValue * (1.0 + maxValue))), data); }
inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::littleEndian24Bit (data) << 8; }
inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::bigEndian24Bit (data) << 8; }
inline void setAsInt32LE (int32 newValue) noexcept { ByteOrder::littleEndian24BitToChars (newValue >> 8, data); }
inline void setAsInt32BE (int32 newValue) noexcept { ByteOrder::bigEndian24BitToChars (newValue >> 8, data); }
inline void clear() noexcept { data[0] = 0; data[1] = 0; data[2] = 0; }
inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int24& source) noexcept { data[0] = source.data[0]; data[1] = source.data[1]; data[2] = source.data[2]; }
char* data;
enum { bytesPerSample = 3, maxValue = 0x7fffff, resolution = (1 << 8), isFloat = 0 };
};
class Int32
{
public:
inline Int32 (void* d) noexcept : data (static_cast <uint32*> (d)) {}
inline void advance() noexcept { ++data; }
inline void skip (int numSamples) noexcept { data += numSamples; }
inline float getAsFloatLE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfBigEndian (*data)); }
inline float getAsFloatBE() const noexcept { return (float) ((1.0 / (1.0 + maxValue)) * (int32) ByteOrder::swapIfLittleEndian (*data)); }
inline void setAsFloatLE (float newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); }
inline void setAsFloatBE (float newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) (maxValue * jlimit (-1.0, 1.0, (double) newValue))); }
inline int32 getAsInt32LE() const noexcept { return (int32) ByteOrder::swapIfBigEndian (*data); }
inline int32 getAsInt32BE() const noexcept { return (int32) ByteOrder::swapIfLittleEndian (*data); }
inline void setAsInt32LE (int32 newValue) noexcept { *data = ByteOrder::swapIfBigEndian ((uint32) newValue); }
inline void setAsInt32BE (int32 newValue) noexcept { *data = ByteOrder::swapIfLittleEndian ((uint32) newValue); }
inline void clear() noexcept { *data = 0; }
inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsInt32LE (source.getAsInt32()); }
template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsInt32BE (source.getAsInt32()); }
inline void copyFromSameType (Int32& source) noexcept { *data = *source.data; }
uint32* data;
enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = 1, isFloat = 0 };
};
class Float32
{
public:
inline Float32 (void* d) noexcept : data (static_cast <float*> (d)) {}
inline void advance() noexcept { ++data; }
inline void skip (int numSamples) noexcept { data += numSamples; }
#if JUCE_BIG_ENDIAN
inline float getAsFloatBE() const noexcept { return *data; }
inline void setAsFloatBE (float newValue) noexcept { *data = newValue; }
inline float getAsFloatLE() const noexcept { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; }
inline void setAsFloatLE (float newValue) noexcept { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); }
#else
inline float getAsFloatLE() const noexcept { return *data; }
inline void setAsFloatLE (float newValue) noexcept { *data = newValue; }
inline float getAsFloatBE() const noexcept { union { uint32 asInt; float asFloat; } n; n.asInt = ByteOrder::swap (*(uint32*) data); return n.asFloat; }
inline void setAsFloatBE (float newValue) noexcept { union { uint32 asInt; float asFloat; } n; n.asFloat = newValue; *(uint32*) data = ByteOrder::swap (n.asInt); }
#endif
inline int32 getAsInt32LE() const noexcept { return (int32) roundToInt (jlimit (-1.0, 1.0, (double) getAsFloatLE()) * (double) maxValue); }
inline int32 getAsInt32BE() const noexcept { return (int32) roundToInt (jlimit (-1.0, 1.0, (double) getAsFloatBE()) * (double) maxValue); }
inline void setAsInt32LE (int32 newValue) noexcept { setAsFloatLE ((float) (newValue * (1.0 / (1.0 + maxValue)))); }
inline void setAsInt32BE (int32 newValue) noexcept { setAsFloatBE ((float) (newValue * (1.0 / (1.0 + maxValue)))); }
inline void clear() noexcept { *data = 0; }
inline void clearMultiple (int num) noexcept { zeromem (data, (size_t) (num * bytesPerSample)) ;}
template <class SourceType> inline void copyFromLE (SourceType& source) noexcept { setAsFloatLE (source.getAsFloat()); }
template <class SourceType> inline void copyFromBE (SourceType& source) noexcept { setAsFloatBE (source.getAsFloat()); }
inline void copyFromSameType (Float32& source) noexcept { *data = *source.data; }
float* data;
enum { bytesPerSample = 4, maxValue = 0x7fffffff, resolution = (1 << 8), isFloat = 1 };
};
//==============================================================================
class NonInterleaved
{
public:
inline NonInterleaved() noexcept {}
inline NonInterleaved (const NonInterleaved&) noexcept {}
inline NonInterleaved (const int) noexcept {}
inline void copyFrom (const NonInterleaved&) noexcept {}
template <class SampleFormatType> inline void advanceData (SampleFormatType& s) noexcept { s.advance(); }
template <class SampleFormatType> inline void advanceDataBy (SampleFormatType& s, int numSamples) noexcept { s.skip (numSamples); }
template <class SampleFormatType> inline void clear (SampleFormatType& s, int numSamples) noexcept { s.clearMultiple (numSamples); }
template <class SampleFormatType> inline static int getNumBytesBetweenSamples (const SampleFormatType&) noexcept { return SampleFormatType::bytesPerSample; }
enum { isInterleavedType = 0, numInterleavedChannels = 1 };
};
class Interleaved
{
public:
inline Interleaved() noexcept : numInterleavedChannels (1) {}
inline Interleaved (const Interleaved& other) noexcept : numInterleavedChannels (other.numInterleavedChannels) {}
inline Interleaved (const int numInterleavedChans) noexcept : numInterleavedChannels (numInterleavedChans) {}
inline void copyFrom (const Interleaved& other) noexcept { numInterleavedChannels = other.numInterleavedChannels; }
template <class SampleFormatType> inline void advanceData (SampleFormatType& s) noexcept { s.skip (numInterleavedChannels); }
template <class SampleFormatType> inline void advanceDataBy (SampleFormatType& s, int numSamples) noexcept { s.skip (numInterleavedChannels * numSamples); }
template <class SampleFormatType> inline void clear (SampleFormatType& s, int numSamples) noexcept { while (--numSamples >= 0) { s.clear(); s.skip (numInterleavedChannels); } }
template <class SampleFormatType> inline int getNumBytesBetweenSamples (const SampleFormatType&) const noexcept { return numInterleavedChannels * SampleFormatType::bytesPerSample; }
int numInterleavedChannels;
enum { isInterleavedType = 1 };
};
//==============================================================================
class NonConst
{
public:
typedef void VoidType;
static inline void* toVoidPtr (VoidType* v) noexcept { return v; }
enum { isConst = 0 };
};
class Const
{
public:
typedef const void VoidType;
static inline void* toVoidPtr (VoidType* v) noexcept { return const_cast <void*> (v); }
enum { isConst = 1 };
};
#endif
//==============================================================================
/**
A pointer to a block of audio data with a particular encoding.
This object can be used to read and write from blocks of encoded audio samples. To create one, you specify
the audio format as a series of template parameters, e.g.
@code
// this creates a pointer for reading from a const array of 16-bit little-endian packed samples.
AudioData::Pointer <AudioData::Int16,
AudioData::LittleEndian,
AudioData::NonInterleaved,
AudioData::Const> pointer (someRawAudioData);
// These methods read the sample that is being pointed to
float firstSampleAsFloat = pointer.getAsFloat();
int32 firstSampleAsInt = pointer.getAsInt32();
++pointer; // moves the pointer to the next sample.
pointer += 3; // skips the next 3 samples.
@endcode
The convertSamples() method lets you copy a range of samples from one format to another, automatically
converting its format.
@see AudioData::Converter
*/
template <typename SampleFormat,
typename Endianness,
typename InterleavingType,
typename Constness>
class Pointer : private InterleavingType // (inherited for EBCO)
{
public:
//==============================================================================
/** Creates a non-interleaved pointer from some raw data in the appropriate format.
This constructor is only used if you've specified the AudioData::NonInterleaved option -
for interleaved formats, use the constructor that also takes a number of channels.
*/
Pointer (typename Constness::VoidType* sourceData) noexcept
: data (Constness::toVoidPtr (sourceData))
{
// If you're using interleaved data, call the other constructor! If you're using non-interleaved data,
// you should pass NonInterleaved as the template parameter for the interleaving type!
static_jassert (InterleavingType::isInterleavedType == 0);
}
/** Creates a pointer from some raw data in the appropriate format with the specified number of interleaved channels.
For non-interleaved data, use the other constructor.
*/
Pointer (typename Constness::VoidType* sourceData, int numInterleavedChannels) noexcept
: InterleavingType (numInterleavedChannels), data (Constness::toVoidPtr (sourceData))
{
}
/** Creates a copy of another pointer. */
Pointer (const Pointer& other) noexcept
: InterleavingType (other), data (other.data)
{
}
Pointer& operator= (const Pointer& other) noexcept
{
InterleavingType::operator= (other);
data = other.data;
return *this;
}
//==============================================================================
/** Returns the value of the first sample as a floating point value.
The value will be in the range -1.0 to 1.0 for integer formats. For floating point
formats, the value could be outside that range, although -1 to 1 is the standard range.
*/
inline float getAsFloat() const noexcept { return Endianness::getAsFloat (data); }
/** Sets the value of the first sample as a floating point value.
(This method can only be used if the AudioData::NonConst option was used).
The value should be in the range -1.0 to 1.0 - for integer formats, values outside that
range will be clipped. For floating point formats, any value passed in here will be
written directly, although -1 to 1 is the standard range.
*/
inline void setAsFloat (float newValue) noexcept
{
static_jassert (Constness::isConst == 0); // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
Endianness::setAsFloat (data, newValue);
}
/** Returns the value of the first sample as a 32-bit integer.
The value returned will be in the range 0x80000000 to 0x7fffffff, and shorter values will be
shifted to fill this range (e.g. if you're reading from 24-bit data, the values will be shifted up
by 8 bits when returned here). If the source data is floating point, values beyond -1.0 to 1.0 will
be clipped so that -1.0 maps onto -0x7fffffff and 1.0 maps to 0x7fffffff.
*/
inline int32 getAsInt32() const noexcept { return Endianness::getAsInt32 (data); }
/** Sets the value of the first sample as a 32-bit integer.
This will be mapped to the range of the format that is being written - see getAsInt32().
*/
inline void setAsInt32 (int32 newValue) noexcept
{
static_jassert (Constness::isConst == 0); // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
Endianness::setAsInt32 (data, newValue);
}
/** Moves the pointer along to the next sample. */
inline Pointer& operator++() noexcept { advance(); return *this; }
/** Moves the pointer back to the previous sample. */
inline Pointer& operator--() noexcept { this->advanceDataBy (data, -1); return *this; }
/** Adds a number of samples to the pointer's position. */
Pointer& operator+= (int samplesToJump) noexcept { this->advanceDataBy (data, samplesToJump); return *this; }
/** Writes a stream of samples into this pointer from another pointer.
This will copy the specified number of samples, converting between formats appropriately.
*/
void convertSamples (Pointer source, int numSamples) const noexcept
{
static_jassert (Constness::isConst == 0); // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
Pointer dest (*this);
while (--numSamples >= 0)
{
dest.data.copyFromSameType (source.data);
dest.advance();
source.advance();
}
}
/** Writes a stream of samples into this pointer from another pointer.
This will copy the specified number of samples, converting between formats appropriately.
*/
template <class OtherPointerType>
void convertSamples (OtherPointerType source, int numSamples) const noexcept
{
static_jassert (Constness::isConst == 0); // trying to write to a const pointer! For a writeable one, use AudioData::NonConst instead!
Pointer dest (*this);
if (source.getRawData() != getRawData() || source.getNumBytesBetweenSamples() >= getNumBytesBetweenSamples())
{
while (--numSamples >= 0)
{
Endianness::copyFrom (dest.data, source);
dest.advance();
++source;
}
}
else // copy backwards if we're increasing the sample width..
{
dest += numSamples;
source += numSamples;
while (--numSamples >= 0)
Endianness::copyFrom ((--dest).data, --source);
}
}
/** Sets a number of samples to zero. */
void clearSamples (int numSamples) const noexcept
{
Pointer dest (*this);
dest.clear (dest.data, numSamples);
}
/** Returns true if the pointer is using a floating-point format. */
static bool isFloatingPoint() noexcept { return (bool) SampleFormat::isFloat; }
/** Returns true if the format is big-endian. */
static bool isBigEndian() noexcept { return (bool) Endianness::isBigEndian; }
/** Returns the number of bytes in each sample (ignoring the number of interleaved channels). */
static int getBytesPerSample() noexcept { return (int) SampleFormat::bytesPerSample; }
/** Returns the number of interleaved channels in the format. */
int getNumInterleavedChannels() const noexcept { return (int) this->numInterleavedChannels; }
/** Returns the number of bytes between the start address of each sample. */
int getNumBytesBetweenSamples() const noexcept { return InterleavingType::getNumBytesBetweenSamples (data); }
/** Returns the accuracy of this format when represented as a 32-bit integer.
This is the smallest number above 0 that can be represented in the sample format, converted to
a 32-bit range. E,g. if the format is 8-bit, its resolution is 0x01000000; if the format is 24-bit,
its resolution is 0x100.
*/
static int get32BitResolution() noexcept { return (int) SampleFormat::resolution; }
/** Returns a pointer to the underlying data. */
const void* getRawData() const noexcept { return data.data; }
private:
//==============================================================================
SampleFormat data;
inline void advance() noexcept { this->advanceData (data); }
Pointer operator++ (int); // private to force you to use the more efficient pre-increment!
Pointer operator-- (int);
};
//==============================================================================
/** A base class for objects that are used to convert between two different sample formats.
The AudioData::ConverterInstance implements this base class and can be templated, so
you can create an instance that converts between two particular formats, and then
store this in the abstract base class.
@see AudioData::ConverterInstance
*/
class Converter
{
public:
virtual ~Converter() {}
/** Converts a sequence of samples from the converter's source format into the dest format. */
virtual void convertSamples (void* destSamples, const void* sourceSamples, int numSamples) const = 0;
/** Converts a sequence of samples from the converter's source format into the dest format.
This method takes sub-channel indexes, which can be used with interleaved formats in order to choose a
particular sub-channel of the data to be used.
*/
virtual void convertSamples (void* destSamples, int destSubChannel,
const void* sourceSamples, int sourceSubChannel, int numSamples) const = 0;
};
//==============================================================================
/**
A class that converts between two templated AudioData::Pointer types, and which
implements the AudioData::Converter interface.
This can be used as a concrete instance of the AudioData::Converter abstract class.
@see AudioData::Converter
*/
template <class SourceSampleType, class DestSampleType>
class ConverterInstance : public Converter
{
public:
ConverterInstance (int numSourceChannels = 1, int numDestChannels = 1)
: sourceChannels (numSourceChannels), destChannels (numDestChannels)
{}
~ConverterInstance() {}
void convertSamples (void* dest, const void* source, int numSamples) const
{
SourceSampleType s (source, sourceChannels);
DestSampleType d (dest, destChannels);
d.convertSamples (s, numSamples);
}
void convertSamples (void* dest, int destSubChannel,
const void* source, int sourceSubChannel, int numSamples) const
{
jassert (destSubChannel < destChannels && sourceSubChannel < sourceChannels);
SourceSampleType s (addBytesToPointer (source, sourceSubChannel * SourceSampleType::getBytesPerSample()), sourceChannels);
DestSampleType d (addBytesToPointer (dest, destSubChannel * DestSampleType::getBytesPerSample()), destChannels);
d.convertSamples (s, numSamples);
}
private:
JUCE_DECLARE_NON_COPYABLE (ConverterInstance)
const int sourceChannels, destChannels;
};
};
//==============================================================================
/**
A set of routines to convert buffers of 32-bit floating point data to and from
various integer formats.
Note that these functions are deprecated - the AudioData class provides a much more
flexible set of conversion classes now.
*/
class JUCE_API AudioDataConverters
{
public:
//==============================================================================
static void convertFloatToInt16LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2);
static void convertFloatToInt16BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 2);
static void convertFloatToInt24LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3);
static void convertFloatToInt24BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 3);
static void convertFloatToInt32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
static void convertFloatToInt32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
static void convertFloatToFloat32LE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
static void convertFloatToFloat32BE (const float* source, void* dest, int numSamples, int destBytesPerSample = 4);
//==============================================================================
static void convertInt16LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2);
static void convertInt16BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 2);
static void convertInt24LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3);
static void convertInt24BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 3);
static void convertInt32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
static void convertInt32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
static void convertFloat32LEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
static void convertFloat32BEToFloat (const void* source, float* dest, int numSamples, int srcBytesPerSample = 4);
//==============================================================================
enum DataFormat
{
int16LE,
int16BE,
int24LE,
int24BE,
int32LE,
int32BE,
float32LE,
float32BE,
};
static void convertFloatToFormat (DataFormat destFormat,
const float* source, void* dest, int numSamples);
static void convertFormatToFloat (DataFormat sourceFormat,
const void* source, float* dest, int numSamples);
//==============================================================================
static void interleaveSamples (const float** source, float* dest,
int numSamples, int numChannels);
static void deinterleaveSamples (const float* source, float** dest,
int numSamples, int numChannels);
private:
AudioDataConverters();
JUCE_DECLARE_NON_COPYABLE (AudioDataConverters)
};
#endif // __JUCE_AUDIODATACONVERTERS_JUCEHEADER__

+ 560
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp View File

@@ -0,0 +1,560 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
AudioSampleBuffer::AudioSampleBuffer (const int numChannels_,
const int numSamples) noexcept
: numChannels (numChannels_),
size (numSamples)
{
jassert (numSamples >= 0);
jassert (numChannels_ > 0);
allocateData();
}
AudioSampleBuffer::AudioSampleBuffer (const AudioSampleBuffer& other) noexcept
: numChannels (other.numChannels),
size (other.size)
{
allocateData();
const size_t numBytes = sizeof (float) * (size_t) size;
for (int i = 0; i < numChannels; ++i)
memcpy (channels[i], other.channels[i], numBytes);
}
void AudioSampleBuffer::allocateData()
{
const size_t channelListSize = sizeof (float*) * (size_t) (numChannels + 1);
allocatedBytes = (size_t) numChannels * (size_t) size * sizeof (float) + channelListSize + 32;
allocatedData.malloc (allocatedBytes);
channels = reinterpret_cast <float**> (allocatedData.getData());
float* chan = (float*) (allocatedData + channelListSize);
for (int i = 0; i < numChannels; ++i)
{
channels[i] = chan;
chan += size;
}
channels [numChannels] = 0;
}
AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
const int numChannels_,
const int numSamples) noexcept
: numChannels (numChannels_),
size (numSamples),
allocatedBytes (0)
{
jassert (numChannels_ > 0);
allocateChannels (dataToReferTo, 0);
}
AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
const int numChannels_,
const int startSample,
const int numSamples) noexcept
: numChannels (numChannels_),
size (numSamples),
allocatedBytes (0)
{
jassert (numChannels_ > 0);
allocateChannels (dataToReferTo, startSample);
}
void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
const int newNumChannels,
const int newNumSamples) noexcept
{
jassert (newNumChannels > 0);
allocatedBytes = 0;
allocatedData.free();
numChannels = newNumChannels;
size = newNumSamples;
allocateChannels (dataToReferTo, 0);
}
void AudioSampleBuffer::allocateChannels (float* const* const dataToReferTo, int offset)
{
// (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
{
channels = static_cast <float**> (preallocatedChannelSpace);
}
else
{
allocatedData.malloc ((size_t) numChannels + 1, sizeof (float*));
channels = reinterpret_cast <float**> (allocatedData.getData());
}
for (int i = 0; i < numChannels; ++i)
{
// you have to pass in the same number of valid pointers as numChannels
jassert (dataToReferTo[i] != nullptr);
channels[i] = dataToReferTo[i] + offset;
}
channels [numChannels] = 0;
}
AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) noexcept
{
if (this != &other)
{
setSize (other.getNumChannels(), other.getNumSamples(), false, false, false);
const size_t numBytes = sizeof (float) * (size_t) size;
for (int i = 0; i < numChannels; ++i)
memcpy (channels[i], other.channels[i], numBytes);
}
return *this;
}
AudioSampleBuffer::~AudioSampleBuffer() noexcept
{
}
void AudioSampleBuffer::setSize (const int newNumChannels,
const int newNumSamples,
const bool keepExistingContent,
const bool clearExtraSpace,
const bool avoidReallocating) noexcept
{
jassert (newNumChannels > 0);
jassert (newNumSamples >= 0);
if (newNumSamples != size || newNumChannels != numChannels)
{
const size_t channelListSize = sizeof (float*) * (size_t) (newNumChannels + 1);
const size_t newTotalBytes = ((size_t) newNumChannels * (size_t) newNumSamples * sizeof (float)) + channelListSize + 32;
if (keepExistingContent)
{
HeapBlock <char, true> newData;
newData.allocate (newTotalBytes, clearExtraSpace);
const size_t numBytesToCopy = sizeof (float) * (size_t) jmin (newNumSamples, size);
float** const newChannels = reinterpret_cast <float**> (newData.getData());
float* newChan = reinterpret_cast <float*> (newData + channelListSize);
for (int j = 0; j < newNumChannels; ++j)
{
newChannels[j] = newChan;
newChan += newNumSamples;
}
const int numChansToCopy = jmin (numChannels, newNumChannels);
for (int i = 0; i < numChansToCopy; ++i)
memcpy (newChannels[i], channels[i], numBytesToCopy);
allocatedData.swapWith (newData);
allocatedBytes = newTotalBytes;
channels = newChannels;
}
else
{
if (avoidReallocating && allocatedBytes >= newTotalBytes)
{
if (clearExtraSpace)
allocatedData.clear (newTotalBytes);
}
else
{
allocatedBytes = newTotalBytes;
allocatedData.allocate (newTotalBytes, clearExtraSpace);
channels = reinterpret_cast <float**> (allocatedData.getData());
}
float* chan = reinterpret_cast <float*> (allocatedData + channelListSize);
for (int i = 0; i < newNumChannels; ++i)
{
channels[i] = chan;
chan += newNumSamples;
}
}
channels [newNumChannels] = 0;
size = newNumSamples;
numChannels = newNumChannels;
}
}
void AudioSampleBuffer::clear() noexcept
{
for (int i = 0; i < numChannels; ++i)
zeromem (channels[i], sizeof (float) * (size_t) size);
}
void AudioSampleBuffer::clear (const int startSample,
const int numSamples) noexcept
{
jassert (startSample >= 0 && startSample + numSamples <= size);
for (int i = 0; i < numChannels; ++i)
zeromem (channels [i] + startSample, sizeof (float) * (size_t) numSamples);
}
void AudioSampleBuffer::clear (const int channel,
const int startSample,
const int numSamples) noexcept
{
jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && startSample + numSamples <= size);
zeromem (channels [channel] + startSample, sizeof (float) * (size_t) numSamples);
}
void AudioSampleBuffer::applyGain (const int channel,
const int startSample,
int numSamples,
const float gain) noexcept
{
jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && startSample + numSamples <= size);
if (gain != 1.0f)
{
float* d = channels [channel] + startSample;
if (gain == 0.0f)
{
zeromem (d, sizeof (float) * (size_t) numSamples);
}
else
{
while (--numSamples >= 0)
*d++ *= gain;
}
}
}
void AudioSampleBuffer::applyGainRamp (const int channel,
const int startSample,
int numSamples,
float startGain,
float endGain) noexcept
{
if (startGain == endGain)
{
applyGain (channel, startSample, numSamples, startGain);
}
else
{
jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && startSample + numSamples <= size);
const float increment = (endGain - startGain) / numSamples;
float* d = channels [channel] + startSample;
while (--numSamples >= 0)
{
*d++ *= startGain;
startGain += increment;
}
}
}
void AudioSampleBuffer::applyGain (const int startSample,
const int numSamples,
const float gain) noexcept
{
for (int i = 0; i < numChannels; ++i)
applyGain (i, startSample, numSamples, gain);
}
void AudioSampleBuffer::applyGainRamp (const int startSample,
const int numSamples,
const float startGain,
const float endGain) noexcept
{
for (int i = 0; i < numChannels; ++i)
applyGainRamp (i, startSample, numSamples, startGain, endGain);
}
void AudioSampleBuffer::addFrom (const int destChannel,
const int destStartSample,
const AudioSampleBuffer& source,
const int sourceChannel,
const int sourceStartSample,
int numSamples,
const float gain) noexcept
{
jassert (&source != this || sourceChannel != destChannel);
jassert (isPositiveAndBelow (destChannel, numChannels));
jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
if (gain != 0.0f && numSamples > 0)
{
float* d = channels [destChannel] + destStartSample;
const float* s = source.channels [sourceChannel] + sourceStartSample;
if (gain != 1.0f)
{
while (--numSamples >= 0)
*d++ += gain * *s++;
}
else
{
while (--numSamples >= 0)
*d++ += *s++;
}
}
}
void AudioSampleBuffer::addFrom (const int destChannel,
const int destStartSample,
const float* source,
int numSamples,
const float gain) noexcept
{
jassert (isPositiveAndBelow (destChannel, numChannels));
jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
jassert (source != nullptr);
if (gain != 0.0f && numSamples > 0)
{
float* d = channels [destChannel] + destStartSample;
if (gain != 1.0f)
{
while (--numSamples >= 0)
*d++ += gain * *source++;
}
else
{
while (--numSamples >= 0)
*d++ += *source++;
}
}
}
void AudioSampleBuffer::addFromWithRamp (const int destChannel,
const int destStartSample,
const float* source,
int numSamples,
float startGain,
const float endGain) noexcept
{
jassert (isPositiveAndBelow (destChannel, numChannels));
jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
jassert (source != nullptr);
if (startGain == endGain)
{
addFrom (destChannel,
destStartSample,
source,
numSamples,
startGain);
}
else
{
if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
{
const float increment = (endGain - startGain) / numSamples;
float* d = channels [destChannel] + destStartSample;
while (--numSamples >= 0)
{
*d++ += startGain * *source++;
startGain += increment;
}
}
}
}
void AudioSampleBuffer::copyFrom (const int destChannel,
const int destStartSample,
const AudioSampleBuffer& source,
const int sourceChannel,
const int sourceStartSample,
int numSamples) noexcept
{
jassert (&source != this || sourceChannel != destChannel);
jassert (isPositiveAndBelow (destChannel, numChannels));
jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
if (numSamples > 0)
{
memcpy (channels [destChannel] + destStartSample,
source.channels [sourceChannel] + sourceStartSample,
sizeof (float) * (size_t) numSamples);
}
}
void AudioSampleBuffer::copyFrom (const int destChannel,
const int destStartSample,
const float* source,
int numSamples) noexcept
{
jassert (isPositiveAndBelow (destChannel, numChannels));
jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
jassert (source != nullptr);
if (numSamples > 0)
{
memcpy (channels [destChannel] + destStartSample,
source,
sizeof (float) * (size_t) numSamples);
}
}
void AudioSampleBuffer::copyFrom (const int destChannel,
const int destStartSample,
const float* source,
int numSamples,
const float gain) noexcept
{
jassert (isPositiveAndBelow (destChannel, numChannels));
jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
jassert (source != nullptr);
if (numSamples > 0)
{
float* d = channels [destChannel] + destStartSample;
if (gain != 1.0f)
{
if (gain == 0)
{
zeromem (d, sizeof (float) * (size_t) numSamples);
}
else
{
while (--numSamples >= 0)
*d++ = gain * *source++;
}
}
else
{
memcpy (d, source, sizeof (float) * (size_t) numSamples);
}
}
}
void AudioSampleBuffer::copyFromWithRamp (const int destChannel,
const int destStartSample,
const float* source,
int numSamples,
float startGain,
float endGain) noexcept
{
jassert (isPositiveAndBelow (destChannel, numChannels));
jassert (destStartSample >= 0 && destStartSample + numSamples <= size);
jassert (source != nullptr);
if (startGain == endGain)
{
copyFrom (destChannel,
destStartSample,
source,
numSamples,
startGain);
}
else
{
if (numSamples > 0 && (startGain != 0.0f || endGain != 0.0f))
{
const float increment = (endGain - startGain) / numSamples;
float* d = channels [destChannel] + destStartSample;
while (--numSamples >= 0)
{
*d++ = startGain * *source++;
startGain += increment;
}
}
}
}
void AudioSampleBuffer::findMinMax (const int channel,
const int startSample,
int numSamples,
float& minVal,
float& maxVal) const noexcept
{
jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && startSample + numSamples <= size);
findMinAndMax (channels [channel] + startSample, numSamples, minVal, maxVal);
}
float AudioSampleBuffer::getMagnitude (const int channel,
const int startSample,
const int numSamples) const noexcept
{
jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && startSample + numSamples <= size);
float mn, mx;
findMinMax (channel, startSample, numSamples, mn, mx);
return jmax (mn, -mn, mx, -mx);
}
float AudioSampleBuffer::getMagnitude (const int startSample,
const int numSamples) const noexcept
{
float mag = 0.0f;
for (int i = 0; i < numChannels; ++i)
mag = jmax (mag, getMagnitude (i, startSample, numSamples));
return mag;
}
float AudioSampleBuffer::getRMSLevel (const int channel,
const int startSample,
const int numSamples) const noexcept
{
jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && startSample + numSamples <= size);
if (numSamples <= 0 || channel < 0 || channel >= numChannels)
return 0.0f;
const float* const data = channels [channel] + startSample;
double sum = 0.0;
for (int i = 0; i < numSamples; ++i)
{
const float sample = data [i];
sum += sample * sample;
}
return (float) std::sqrt (sum / numSamples);
}

+ 444
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h View File

@@ -0,0 +1,444 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__
#define __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__
//==============================================================================
/**
A multi-channel buffer of 32-bit floating point audio samples.
*/
class JUCE_API AudioSampleBuffer
{
public:
//==============================================================================
/** Creates a buffer with a specified number of channels and samples.
The contents of the buffer will initially be undefined, so use clear() to
set all the samples to zero.
The buffer will allocate its memory internally, and this will be released
when the buffer is deleted. If the memory can't be allocated, this will
throw a std::bad_alloc exception.
*/
AudioSampleBuffer (int numChannels,
int numSamples) noexcept;
/** Creates a buffer using a pre-allocated block of memory.
Note that if the buffer is resized or its number of channels is changed, it
will re-allocate memory internally and copy the existing data to this new area,
so it will then stop directly addressing this memory.
@param dataToReferTo a pre-allocated array containing pointers to the data
for each channel that should be used by this buffer. The
buffer will only refer to this memory, it won't try to delete
it when the buffer is deleted or resized.
@param numChannels the number of channels to use - this must correspond to the
number of elements in the array passed in
@param numSamples the number of samples to use - this must correspond to the
size of the arrays passed in
*/
AudioSampleBuffer (float* const* dataToReferTo,
int numChannels,
int numSamples) noexcept;
/** Creates a buffer using a pre-allocated block of memory.
Note that if the buffer is resized or its number of channels is changed, it
will re-allocate memory internally and copy the existing data to this new area,
so it will then stop directly addressing this memory.
@param dataToReferTo a pre-allocated array containing pointers to the data
for each channel that should be used by this buffer. The
buffer will only refer to this memory, it won't try to delete
it when the buffer is deleted or resized.
@param numChannels the number of channels to use - this must correspond to the
number of elements in the array passed in
@param startSample the offset within the arrays at which the data begins
@param numSamples the number of samples to use - this must correspond to the
size of the arrays passed in
*/
AudioSampleBuffer (float* const* dataToReferTo,
int numChannels,
int startSample,
int numSamples) noexcept;
/** Copies another buffer.
This buffer will make its own copy of the other's data, unless the buffer was created
using an external data buffer, in which case boths buffers will just point to the same
shared block of data.
*/
AudioSampleBuffer (const AudioSampleBuffer& other) noexcept;
/** Copies another buffer onto this one.
This buffer's size will be changed to that of the other buffer.
*/
AudioSampleBuffer& operator= (const AudioSampleBuffer& other) noexcept;
/** Destructor.
This will free any memory allocated by the buffer.
*/
virtual ~AudioSampleBuffer() noexcept;
//==============================================================================
/** Returns the number of channels of audio data that this buffer contains.
@see getSampleData
*/
int getNumChannels() const noexcept { return numChannels; }
/** Returns the number of samples allocated in each of the buffer's channels.
@see getSampleData
*/
int getNumSamples() const noexcept { return size; }
/** Returns a pointer one of the buffer's channels.
For speed, this doesn't check whether the channel number is out of range,
so be careful when using it!
*/
float* getSampleData (const int channelNumber) const noexcept
{
jassert (isPositiveAndBelow (channelNumber, numChannels));
return channels [channelNumber];
}
/** Returns a pointer to a sample in one of the buffer's channels.
For speed, this doesn't check whether the channel and sample number
are out-of-range, so be careful when using it!
*/
float* getSampleData (const int channelNumber,
const int sampleOffset) const noexcept
{
jassert (isPositiveAndBelow (channelNumber, numChannels));
jassert (isPositiveAndBelow (sampleOffset, size));
return channels [channelNumber] + sampleOffset;
}
/** Returns an array of pointers to the channels in the buffer.
Don't modify any of the pointers that are returned, and bear in mind that
these will become invalid if the buffer is resized.
*/
float** getArrayOfChannels() const noexcept { return channels; }
//==============================================================================
/** Changes the buffer's size or number of channels.
This can expand or contract the buffer's length, and add or remove channels.
If keepExistingContent is true, it will try to preserve as much of the
old data as it can in the new buffer.
If clearExtraSpace is true, then any extra channels or space that is
allocated will be also be cleared. If false, then this space is left
uninitialised.
If avoidReallocating is true, then changing the buffer's size won't reduce the
amount of memory that is currently allocated (but it will still increase it if
the new size is bigger than the amount it currently has). If this is false, then
a new allocation will be done so that the buffer uses takes up the minimum amount
of memory that it needs.
If the required memory can't be allocated, this will throw a std::bad_alloc exception.
*/
void setSize (int newNumChannels,
int newNumSamples,
bool keepExistingContent = false,
bool clearExtraSpace = false,
bool avoidReallocating = false) noexcept;
/** Makes this buffer point to a pre-allocated set of channel data arrays.
There's also a constructor that lets you specify arrays like this, but this
lets you change the channels dynamically.
Note that if the buffer is resized or its number of channels is changed, it
will re-allocate memory internally and copy the existing data to this new area,
so it will then stop directly addressing this memory.
@param dataToReferTo a pre-allocated array containing pointers to the data
for each channel that should be used by this buffer. The
buffer will only refer to this memory, it won't try to delete
it when the buffer is deleted or resized.
@param numChannels the number of channels to use - this must correspond to the
number of elements in the array passed in
@param numSamples the number of samples to use - this must correspond to the
size of the arrays passed in
*/
void setDataToReferTo (float** dataToReferTo,
int numChannels,
int numSamples) noexcept;
//==============================================================================
/** Clears all the samples in all channels. */
void clear() noexcept;
/** Clears a specified region of all the channels.
For speed, this doesn't check whether the channel and sample number
are in-range, so be careful!
*/
void clear (int startSample,
int numSamples) noexcept;
/** Clears a specified region of just one channel.
For speed, this doesn't check whether the channel and sample number
are in-range, so be careful!
*/
void clear (int channel,
int startSample,
int numSamples) noexcept;
/** Applies a gain multiple to a region of one channel.
For speed, this doesn't check whether the channel and sample number
are in-range, so be careful!
*/
void applyGain (int channel,
int startSample,
int numSamples,
float gain) noexcept;
/** Applies a gain multiple to a region of all the channels.
For speed, this doesn't check whether the sample numbers
are in-range, so be careful!
*/
void applyGain (int startSample,
int numSamples,
float gain) noexcept;
/** Applies a range of gains to a region of a channel.
The gain that is applied to each sample will vary from
startGain on the first sample to endGain on the last Sample,
so it can be used to do basic fades.
For speed, this doesn't check whether the sample numbers
are in-range, so be careful!
*/
void applyGainRamp (int channel,
int startSample,
int numSamples,
float startGain,
float endGain) noexcept;
/** Applies a range of gains to a region of all channels.
The gain that is applied to each sample will vary from
startGain on the first sample to endGain on the last Sample,
so it can be used to do basic fades.
For speed, this doesn't check whether the sample numbers
are in-range, so be careful!
*/
void applyGainRamp (int startSample,
int numSamples,
float startGain,
float endGain) noexcept;
/** Adds samples from another buffer to this one.
@param destChannel the channel within this buffer to add the samples to
@param destStartSample the start sample within this buffer's channel
@param source the source buffer to add from
@param sourceChannel the channel within the source buffer to read from
@param sourceStartSample the offset within the source buffer's channel to start reading samples from
@param numSamples the number of samples to process
@param gainToApplyToSource an optional gain to apply to the source samples before they are
added to this buffer's samples
@see copyFrom
*/
void addFrom (int destChannel,
int destStartSample,
const AudioSampleBuffer& source,
int sourceChannel,
int sourceStartSample,
int numSamples,
float gainToApplyToSource = 1.0f) noexcept;
/** Adds samples from an array of floats to one of the channels.
@param destChannel the channel within this buffer to add the samples to
@param destStartSample the start sample within this buffer's channel
@param source the source data to use
@param numSamples the number of samples to process
@param gainToApplyToSource an optional gain to apply to the source samples before they are
added to this buffer's samples
@see copyFrom
*/
void addFrom (int destChannel,
int destStartSample,
const float* source,
int numSamples,
float gainToApplyToSource = 1.0f) noexcept;
/** Adds samples from an array of floats, applying a gain ramp to them.
@param destChannel the channel within this buffer to add the samples to
@param destStartSample the start sample within this buffer's channel
@param source the source data to use
@param numSamples the number of samples to process
@param startGain the gain to apply to the first sample (this is multiplied with
the source samples before they are added to this buffer)
@param endGain the gain to apply to the final sample. The gain is linearly
interpolated between the first and last samples.
*/
void addFromWithRamp (int destChannel,
int destStartSample,
const float* source,
int numSamples,
float startGain,
float endGain) noexcept;
/** Copies samples from another buffer to this one.
@param destChannel the channel within this buffer to copy the samples to
@param destStartSample the start sample within this buffer's channel
@param source the source buffer to read from
@param sourceChannel the channel within the source buffer to read from
@param sourceStartSample the offset within the source buffer's channel to start reading samples from
@param numSamples the number of samples to process
@see addFrom
*/
void copyFrom (int destChannel,
int destStartSample,
const AudioSampleBuffer& source,
int sourceChannel,
int sourceStartSample,
int numSamples) noexcept;
/** Copies samples from an array of floats into one of the channels.
@param destChannel the channel within this buffer to copy the samples to
@param destStartSample the start sample within this buffer's channel
@param source the source buffer to read from
@param numSamples the number of samples to process
@see addFrom
*/
void copyFrom (int destChannel,
int destStartSample,
const float* source,
int numSamples) noexcept;
/** Copies samples from an array of floats into one of the channels, applying a gain to it.
@param destChannel the channel within this buffer to copy the samples to
@param destStartSample the start sample within this buffer's channel
@param source the source buffer to read from
@param numSamples the number of samples to process
@param gain the gain to apply
@see addFrom
*/
void copyFrom (int destChannel,
int destStartSample,
const float* source,
int numSamples,
float gain) noexcept;
/** Copies samples from an array of floats into one of the channels, applying a gain ramp.
@param destChannel the channel within this buffer to copy the samples to
@param destStartSample the start sample within this buffer's channel
@param source the source buffer to read from
@param numSamples the number of samples to process
@param startGain the gain to apply to the first sample (this is multiplied with
the source samples before they are copied to this buffer)
@param endGain the gain to apply to the final sample. The gain is linearly
interpolated between the first and last samples.
@see addFrom
*/
void copyFromWithRamp (int destChannel,
int destStartSample,
const float* source,
int numSamples,
float startGain,
float endGain) noexcept;
/** Finds the highest and lowest sample values in a given range.
@param channel the channel to read from
@param startSample the start sample within the channel
@param numSamples the number of samples to check
@param minVal on return, the lowest value that was found
@param maxVal on return, the highest value that was found
*/
void findMinMax (int channel,
int startSample,
int numSamples,
float& minVal,
float& maxVal) const noexcept;
/** Finds the highest absolute sample value within a region of a channel.
*/
float getMagnitude (int channel,
int startSample,
int numSamples) const noexcept;
/** Finds the highest absolute sample value within a region on all channels.
*/
float getMagnitude (int startSample,
int numSamples) const noexcept;
/** Returns the root mean squared level for a region of a channel.
*/
float getRMSLevel (int channel,
int startSample,
int numSamples) const noexcept;
private:
//==============================================================================
int numChannels, size;
size_t allocatedBytes;
float** channels;
HeapBlock <char, true> allocatedData;
float* preallocatedChannelSpace [32];
void allocateData();
void allocateChannels (float* const* dataToReferTo, int offset);
JUCE_LEAK_DETECTOR (AudioSampleBuffer)
};
#endif // __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__

+ 104
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h View File

@@ -0,0 +1,104 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_DECIBELS_JUCEHEADER__
#define __JUCE_DECIBELS_JUCEHEADER__
//==============================================================================
/**
This class contains some helpful static methods for dealing with decibel values.
*/
class Decibels
{
public:
//==============================================================================
/** Converts a dBFS value to its equivalent gain level.
A gain of 1.0 = 0 dB, and lower gains map onto negative decibel values. Any
decibel value lower than minusInfinityDb will return a gain of 0.
*/
template <typename Type>
static Type decibelsToGain (const Type decibels,
const Type minusInfinityDb = (Type) defaultMinusInfinitydB)
{
return decibels > minusInfinityDb ? powf ((Type) 10.0, decibels * (Type) 0.05)
: Type();
}
/** Converts a gain level into a dBFS value.
A gain of 1.0 = 0 dB, and lower gains map onto negative decibel values.
If the gain is 0 (or negative), then the method will return the value
provided as minusInfinityDb.
*/
template <typename Type>
static Type gainToDecibels (const Type gain,
const Type minusInfinityDb = (Type) defaultMinusInfinitydB)
{
return gain > Type() ? jmax (minusInfinityDb, (Type) std::log10 (gain) * (Type) 20.0)
: minusInfinityDb;
}
//==============================================================================
/** Converts a decibel reading to a string, with the 'dB' suffix.
If the decibel value is lower than minusInfinityDb, the return value will
be "-INF dB".
*/
template <typename Type>
static String toString (const Type decibels,
const int decimalPlaces = 2,
const Type minusInfinityDb = (Type) defaultMinusInfinitydB)
{
String s;
if (decibels <= minusInfinityDb)
{
s = "-INF dB";
}
else
{
if (decibels >= Type())
s << '+';
s << String (decibels, decimalPlaces) << " dB";
}
return s;
}
private:
//==============================================================================
enum
{
defaultMinusInfinitydB = -100
};
Decibels(); // This class can't be instantiated, it's just a holder for static methods..
JUCE_DECLARE_NON_COPYABLE (Decibels)
};
#endif // __JUCE_DECIBELS_JUCEHEADER__

+ 252
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.cpp View File

@@ -0,0 +1,252 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#if JUCE_INTEL
#define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0;
#else
#define JUCE_SNAP_TO_ZERO(n)
#endif
//==============================================================================
IIRFilter::IIRFilter()
: active (false)
{
reset();
}
IIRFilter::IIRFilter (const IIRFilter& other)
: active (other.active)
{
const ScopedLock sl (other.processLock);
memcpy (coefficients, other.coefficients, sizeof (coefficients));
reset();
}
IIRFilter::~IIRFilter()
{
}
//==============================================================================
void IIRFilter::reset() noexcept
{
const ScopedLock sl (processLock);
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
}
float IIRFilter::processSingleSampleRaw (const float in) noexcept
{
float out = coefficients[0] * in
+ coefficients[1] * x1
+ coefficients[2] * x2
- coefficients[4] * y1
- coefficients[5] * y2;
JUCE_SNAP_TO_ZERO (out);
x2 = x1;
x1 = in;
y2 = y1;
y1 = out;
return out;
}
void IIRFilter::processSamples (float* const samples,
const int numSamples) noexcept
{
const ScopedLock sl (processLock);
if (active)
{
for (int i = 0; i < numSamples; ++i)
{
const float in = samples[i];
float out = coefficients[0] * in
+ coefficients[1] * x1
+ coefficients[2] * x2
- coefficients[4] * y1
- coefficients[5] * y2;
JUCE_SNAP_TO_ZERO (out);
x2 = x1;
x1 = in;
y2 = y1;
y1 = out;
samples[i] = out;
}
}
}
//==============================================================================
void IIRFilter::makeLowPass (const double sampleRate,
const double frequency) noexcept
{
jassert (sampleRate > 0);
const double n = 1.0 / tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
setCoefficients (c1,
c1 * 2.0f,
c1,
1.0,
c1 * 2.0 * (1.0 - nSquared),
c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
}
void IIRFilter::makeHighPass (const double sampleRate,
const double frequency) noexcept
{
const double n = tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
setCoefficients (c1,
c1 * -2.0f,
c1,
1.0,
c1 * 2.0 * (nSquared - 1.0),
c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
}
void IIRFilter::makeLowShelf (const double sampleRate,
const double cutOffFrequency,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
const double A = jmax (0.0f, gainFactor);
const double aminus1 = A - 1.0;
const double aplus1 = A + 1.0;
const double omega = (double_Pi * 2.0 * jmax (cutOffFrequency, 2.0)) / sampleRate;
const double coso = std::cos (omega);
const double beta = std::sin (omega) * std::sqrt (A) / Q;
const double aminus1TimesCoso = aminus1 * coso;
setCoefficients (A * (aplus1 - aminus1TimesCoso + beta),
A * 2.0 * (aminus1 - aplus1 * coso),
A * (aplus1 - aminus1TimesCoso - beta),
aplus1 + aminus1TimesCoso + beta,
-2.0 * (aminus1 + aplus1 * coso),
aplus1 + aminus1TimesCoso - beta);
}
void IIRFilter::makeHighShelf (const double sampleRate,
const double cutOffFrequency,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
const double A = jmax (0.0f, gainFactor);
const double aminus1 = A - 1.0;
const double aplus1 = A + 1.0;
const double omega = (double_Pi * 2.0 * jmax (cutOffFrequency, 2.0)) / sampleRate;
const double coso = std::cos (omega);
const double beta = std::sin (omega) * std::sqrt (A) / Q;
const double aminus1TimesCoso = aminus1 * coso;
setCoefficients (A * (aplus1 + aminus1TimesCoso + beta),
A * -2.0 * (aminus1 + aplus1 * coso),
A * (aplus1 + aminus1TimesCoso - beta),
aplus1 - aminus1TimesCoso + beta,
2.0 * (aminus1 - aplus1 * coso),
aplus1 - aminus1TimesCoso - beta);
}
void IIRFilter::makeBandPass (const double sampleRate,
const double centreFrequency,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
const double A = jmax (0.0f, gainFactor);
const double omega = (double_Pi * 2.0 * jmax (centreFrequency, 2.0)) / sampleRate;
const double alpha = 0.5 * std::sin (omega) / Q;
const double c2 = -2.0 * std::cos (omega);
const double alphaTimesA = alpha * A;
const double alphaOverA = alpha / A;
setCoefficients (1.0 + alphaTimesA,
c2,
1.0 - alphaTimesA,
1.0 + alphaOverA,
c2,
1.0 - alphaOverA);
}
void IIRFilter::makeInactive() noexcept
{
const ScopedLock sl (processLock);
active = false;
}
//==============================================================================
void IIRFilter::copyCoefficientsFrom (const IIRFilter& other) noexcept
{
const ScopedLock sl (processLock);
memcpy (coefficients, other.coefficients, sizeof (coefficients));
active = other.active;
}
//==============================================================================
void IIRFilter::setCoefficients (double c1, double c2, double c3,
double c4, double c5, double c6) noexcept
{
const double a = 1.0 / c4;
c1 *= a;
c2 *= a;
c3 *= a;
c5 *= a;
c6 *= a;
const ScopedLock sl (processLock);
coefficients[0] = (float) c1;
coefficients[1] = (float) c2;
coefficients[2] = (float) c3;
coefficients[3] = (float) c4;
coefficients[4] = (float) c5;
coefficients[5] = (float) c6;
active = true;
}
#undef JUCE_SNAP_TO_ZERO

+ 149
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.h View File

@@ -0,0 +1,149 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_IIRFILTER_JUCEHEADER__
#define __JUCE_IIRFILTER_JUCEHEADER__
//==============================================================================
/**
An IIR filter that can perform low, high, or band-pass filtering on an
audio signal.
@see IIRFilterAudioSource
*/
class JUCE_API IIRFilter
{
public:
//==============================================================================
/** Creates a filter.
Initially the filter is inactive, so will have no effect on samples that
you process with it. Use the appropriate method to turn it into the type
of filter needed.
*/
IIRFilter();
/** Creates a copy of another filter. */
IIRFilter (const IIRFilter& other);
/** Destructor. */
~IIRFilter();
//==============================================================================
/** Resets the filter's processing pipeline, ready to start a new stream of data.
Note that this clears the processing state, but the type of filter and
its coefficients aren't changed. To put a filter into an inactive state, use
the makeInactive() method.
*/
void reset() noexcept;
/** Performs the filter operation on the given set of samples.
*/
void processSamples (float* samples,
int numSamples) noexcept;
/** Processes a single sample, without any locking or checking.
Use this if you need fast processing of a single value, but be aware that
this isn't thread-safe in the way that processSamples() is.
*/
float processSingleSampleRaw (float sample) noexcept;
//==============================================================================
/** Sets the filter up to act as a low-pass filter.
*/
void makeLowPass (double sampleRate,
double frequency) noexcept;
/** Sets the filter up to act as a high-pass filter.
*/
void makeHighPass (double sampleRate,
double frequency) noexcept;
//==============================================================================
/** Sets the filter up to act as a low-pass shelf filter with variable Q and gain.
The gain is a scale factor that the low frequencies are multiplied by, so values
greater than 1.0 will boost the low frequencies, values less than 1.0 will
attenuate them.
*/
void makeLowShelf (double sampleRate,
double cutOffFrequency,
double Q,
float gainFactor) noexcept;
/** Sets the filter up to act as a high-pass shelf filter with variable Q and gain.
The gain is a scale factor that the high frequencies are multiplied by, so values
greater than 1.0 will boost the high frequencies, values less than 1.0 will
attenuate them.
*/
void makeHighShelf (double sampleRate,
double cutOffFrequency,
double Q,
float gainFactor) noexcept;
/** Sets the filter up to act as a band pass filter centred around a
frequency, with a variable Q and gain.
The gain is a scale factor that the centre frequencies are multiplied by, so
values greater than 1.0 will boost the centre frequencies, values less than
1.0 will attenuate them.
*/
void makeBandPass (double sampleRate,
double centreFrequency,
double Q,
float gainFactor) noexcept;
/** Clears the filter's coefficients so that it becomes inactive.
*/
void makeInactive() noexcept;
//==============================================================================
/** Makes this filter duplicate the set-up of another one.
*/
void copyCoefficientsFrom (const IIRFilter& other) noexcept;
protected:
//==============================================================================
CriticalSection processLock;
void setCoefficients (double c1, double c2, double c3,
double c4, double c5, double c6) noexcept;
bool active;
float coefficients[6];
float x1, x2, y1, y2;
// (use the copyCoefficientsFrom() method instead of this operator)
IIRFilter& operator= (const IIRFilter&);
JUCE_LEAK_DETECTOR (IIRFilter)
};
#endif // __JUCE_IIRFILTER_JUCEHEADER__

+ 321
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Reverb.h View File

@@ -0,0 +1,321 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_REVERB_JUCEHEADER__
#define __JUCE_REVERB_JUCEHEADER__
//==============================================================================
/**
Performs a simple reverb effect on a stream of audio data.
This is a simple stereo reverb, based on the technique and tunings used in FreeVerb.
Use setSampleRate() to prepare it, and then call processStereo() or processMono() to
apply the reverb to your audio data.
@see ReverbAudioSource
*/
class Reverb
{
public:
//==============================================================================
Reverb()
{
setParameters (Parameters());
setSampleRate (44100.0);
}
//==============================================================================
/** Holds the parameters being used by a Reverb object. */
struct Parameters
{
Parameters() noexcept
: roomSize (0.5f),
damping (0.5f),
wetLevel (0.33f),
dryLevel (0.4f),
width (1.0f),
freezeMode (0)
{}
float roomSize; /**< Room size, 0 to 1.0, where 1.0 is big, 0 is small. */
float damping; /**< Damping, 0 to 1.0, where 0 is not damped, 1.0 is fully damped. */
float wetLevel; /**< Wet level, 0 to 1.0 */
float dryLevel; /**< Dry level, 0 to 1.0 */
float width; /**< Reverb width, 0 to 1.0, where 1.0 is very wide. */
float freezeMode; /**< Freeze mode - values < 0.5 are "normal" mode, values > 0.5
put the reverb into a continuous feedback loop. */
};
//==============================================================================
/** Returns the reverb's current parameters. */
const Parameters& getParameters() const noexcept { return parameters; }
/** Applies a new set of parameters to the reverb.
Note that this doesn't attempt to lock the reverb, so if you call this in parallel with
the process method, you may get artifacts.
*/
void setParameters (const Parameters& newParams)
{
const float wetScaleFactor = 3.0f;
const float dryScaleFactor = 2.0f;
const float wet = newParams.wetLevel * wetScaleFactor;
wet1 = wet * (newParams.width * 0.5f + 0.5f);
wet2 = wet * (1.0f - newParams.width) * 0.5f;
dry = newParams.dryLevel * dryScaleFactor;
gain = isFrozen (newParams.freezeMode) ? 0.0f : 0.015f;
parameters = newParams;
shouldUpdateDamping = true;
}
//==============================================================================
/** Sets the sample rate that will be used for the reverb.
You must call this before the process methods, in order to tell it the correct sample rate.
*/
void setSampleRate (const double sampleRate)
{
jassert (sampleRate > 0);
static const short combTunings[] = { 1116, 1188, 1277, 1356, 1422, 1491, 1557, 1617 }; // (at 44100Hz)
static const short allPassTunings[] = { 556, 441, 341, 225 };
const int stereoSpread = 23;
const int intSampleRate = (int) sampleRate;
for (int i = 0; i < numCombs; ++i)
{
comb[0][i].setSize ((intSampleRate * combTunings[i]) / 44100);
comb[1][i].setSize ((intSampleRate * (combTunings[i] + stereoSpread)) / 44100);
}
for (int i = 0; i < numAllPasses; ++i)
{
allPass[0][i].setSize ((intSampleRate * allPassTunings[i]) / 44100);
allPass[1][i].setSize ((intSampleRate * (allPassTunings[i] + stereoSpread)) / 44100);
}
shouldUpdateDamping = true;
}
/** Clears the reverb's buffers. */
void reset()
{
for (int j = 0; j < numChannels; ++j)
{
for (int i = 0; i < numCombs; ++i)
comb[j][i].clear();
for (int i = 0; i < numAllPasses; ++i)
allPass[j][i].clear();
}
}
//==============================================================================
/** Applies the reverb to two stereo channels of audio data. */
void processStereo (float* const left, float* const right, const int numSamples) noexcept
{
jassert (left != nullptr && right != nullptr);
if (shouldUpdateDamping)
updateDamping();
for (int i = 0; i < numSamples; ++i)
{
const float input = (left[i] + right[i]) * gain;
float outL = 0, outR = 0;
for (int j = 0; j < numCombs; ++j) // accumulate the comb filters in parallel
{
outL += comb[0][j].process (input);
outR += comb[1][j].process (input);
}
for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series
{
outL = allPass[0][j].process (outL);
outR = allPass[1][j].process (outR);
}
left[i] = outL * wet1 + outR * wet2 + left[i] * dry;
right[i] = outR * wet1 + outL * wet2 + right[i] * dry;
}
}
/** Applies the reverb to a single mono channel of audio data. */
void processMono (float* const samples, const int numSamples) noexcept
{
jassert (samples != nullptr);
if (shouldUpdateDamping)
updateDamping();
for (int i = 0; i < numSamples; ++i)
{
const float input = samples[i] * gain;
float output = 0;
for (int j = 0; j < numCombs; ++j) // accumulate the comb filters in parallel
output += comb[0][j].process (input);
for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series
output = allPass[0][j].process (output);
samples[i] = output * wet1 + input * dry;
}
}
private:
//==============================================================================
Parameters parameters;
volatile bool shouldUpdateDamping;
float gain, wet1, wet2, dry;
inline static bool isFrozen (const float freezeMode) noexcept { return freezeMode >= 0.5f; }
void updateDamping() noexcept
{
const float roomScaleFactor = 0.28f;
const float roomOffset = 0.7f;
const float dampScaleFactor = 0.4f;
shouldUpdateDamping = false;
if (isFrozen (parameters.freezeMode))
setDamping (0.0f, 1.0f);
else
setDamping (parameters.damping * dampScaleFactor,
parameters.roomSize * roomScaleFactor + roomOffset);
}
void setDamping (const float dampingToUse, const float roomSizeToUse) noexcept
{
for (int j = 0; j < numChannels; ++j)
for (int i = numCombs; --i >= 0;)
comb[j][i].setFeedbackAndDamp (roomSizeToUse, dampingToUse);
}
//==============================================================================
class CombFilter
{
public:
CombFilter() noexcept : bufferSize (0), bufferIndex (0) {}
void setSize (const int size)
{
if (size != bufferSize)
{
bufferIndex = 0;
buffer.malloc ((size_t) size);
bufferSize = size;
}
clear();
}
void clear() noexcept
{
last = 0;
buffer.clear ((size_t) bufferSize);
}
void setFeedbackAndDamp (const float f, const float d) noexcept
{
damp1 = d;
damp2 = 1.0f - d;
feedback = f;
}
inline float process (const float input) noexcept
{
const float output = buffer [bufferIndex];
last = (output * damp2) + (last * damp1);
JUCE_UNDENORMALISE (last);
float temp = input + (last * feedback);
JUCE_UNDENORMALISE (temp);
buffer [bufferIndex] = temp;
bufferIndex = (bufferIndex + 1) % bufferSize;
return output;
}
private:
HeapBlock<float> buffer;
int bufferSize, bufferIndex;
float feedback, last, damp1, damp2;
JUCE_DECLARE_NON_COPYABLE (CombFilter)
};
//==============================================================================
class AllPassFilter
{
public:
AllPassFilter() noexcept : bufferSize (0), bufferIndex (0) {}
void setSize (const int size)
{
if (size != bufferSize)
{
bufferIndex = 0;
buffer.malloc ((size_t) size);
bufferSize = size;
}
clear();
}
void clear() noexcept
{
buffer.clear ((size_t) bufferSize);
}
inline float process (const float input) noexcept
{
const float bufferedValue = buffer [bufferIndex];
float temp = input + (bufferedValue * 0.5f);
JUCE_UNDENORMALISE (temp);
buffer [bufferIndex] = temp;
bufferIndex = (bufferIndex + 1) % bufferSize;
return bufferedValue - input;
}
private:
HeapBlock<float> buffer;
int bufferSize, bufferIndex;
JUCE_DECLARE_NON_COPYABLE (AllPassFilter)
};
enum { numCombs = 8, numAllPasses = 4, numChannels = 2 };
CombFilter comb [numChannels][numCombs];
AllPassFilter allPass [numChannels][numAllPasses];
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Reverb)
};
#endif // __JUCE_REVERB_JUCEHEADER__

+ 63
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.cpp View File

@@ -0,0 +1,63 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#if defined (__JUCE_AUDIO_BASICS_JUCEHEADER__) && ! JUCE_AMALGAMATED_INCLUDE
/* When you add this cpp file to your project, you mustn't include it in a file where you've
already included any other headers - just put it inside a file on its own, possibly with your config
flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
header files that the compiler may be using.
*/
#error "Incorrect use of JUCE cpp file"
#endif
// Your project must contain an AppConfig.h file with your project-specific settings in it,
// and your header search path must make it accessible to the module's files.
#include "AppConfig.h"
#include "juce_audio_basics.h"
namespace juce
{
// START_AUTOINCLUDE buffers/*.cpp, effects/*.cpp, midi/*.cpp, sources/*.cpp, synthesisers/*.cpp
#include "buffers/juce_AudioDataConverters.cpp"
#include "buffers/juce_AudioSampleBuffer.cpp"
#include "effects/juce_IIRFilter.cpp"
#include "midi/juce_MidiBuffer.cpp"
#include "midi/juce_MidiFile.cpp"
#include "midi/juce_MidiKeyboardState.cpp"
#include "midi/juce_MidiMessage.cpp"
#include "midi/juce_MidiMessageSequence.cpp"
#include "sources/juce_BufferingAudioSource.cpp"
#include "sources/juce_ChannelRemappingAudioSource.cpp"
#include "sources/juce_IIRFilterAudioSource.cpp"
#include "sources/juce_MixerAudioSource.cpp"
#include "sources/juce_ResamplingAudioSource.cpp"
#include "sources/juce_ReverbAudioSource.cpp"
#include "sources/juce_ToneGeneratorAudioSource.cpp"
#include "synthesisers/juce_Synthesiser.cpp"
// END_AUTOINCLUDE
}

+ 100
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h View File

@@ -0,0 +1,100 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIO_BASICS_JUCEHEADER__
#define __JUCE_AUDIO_BASICS_JUCEHEADER__
#include "../juce_core/juce_core.h"
//=============================================================================
namespace juce
{
// START_AUTOINCLUDE buffers, effects, midi, sources, synthesisers
#ifndef __JUCE_AUDIODATACONVERTERS_JUCEHEADER__
#include "buffers/juce_AudioDataConverters.h"
#endif
#ifndef __JUCE_AUDIOSAMPLEBUFFER_JUCEHEADER__
#include "buffers/juce_AudioSampleBuffer.h"
#endif
#ifndef __JUCE_DECIBELS_JUCEHEADER__
#include "effects/juce_Decibels.h"
#endif
#ifndef __JUCE_IIRFILTER_JUCEHEADER__
#include "effects/juce_IIRFilter.h"
#endif
#ifndef __JUCE_REVERB_JUCEHEADER__
#include "effects/juce_Reverb.h"
#endif
#ifndef __JUCE_MIDIBUFFER_JUCEHEADER__
#include "midi/juce_MidiBuffer.h"
#endif
#ifndef __JUCE_MIDIFILE_JUCEHEADER__
#include "midi/juce_MidiFile.h"
#endif
#ifndef __JUCE_MIDIKEYBOARDSTATE_JUCEHEADER__
#include "midi/juce_MidiKeyboardState.h"
#endif
#ifndef __JUCE_MIDIMESSAGE_JUCEHEADER__
#include "midi/juce_MidiMessage.h"
#endif
#ifndef __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__
#include "midi/juce_MidiMessageSequence.h"
#endif
#ifndef __JUCE_AUDIOSOURCE_JUCEHEADER__
#include "sources/juce_AudioSource.h"
#endif
#ifndef __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__
#include "sources/juce_BufferingAudioSource.h"
#endif
#ifndef __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__
#include "sources/juce_ChannelRemappingAudioSource.h"
#endif
#ifndef __JUCE_IIRFILTERAUDIOSOURCE_JUCEHEADER__
#include "sources/juce_IIRFilterAudioSource.h"
#endif
#ifndef __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__
#include "sources/juce_MixerAudioSource.h"
#endif
#ifndef __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__
#include "sources/juce_PositionableAudioSource.h"
#endif
#ifndef __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__
#include "sources/juce_ResamplingAudioSource.h"
#endif
#ifndef __JUCE_REVERBAUDIOSOURCE_JUCEHEADER__
#include "sources/juce_ReverbAudioSource.h"
#endif
#ifndef __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__
#include "sources/juce_ToneGeneratorAudioSource.h"
#endif
#ifndef __JUCE_SYNTHESISER_JUCEHEADER__
#include "synthesisers/juce_Synthesiser.h"
#endif
// END_AUTOINCLUDE
}
#endif // __JUCE_AUDIO_BASICS_JUCEHEADER__

+ 26
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.mm View File

@@ -0,0 +1,26 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#include "juce_audio_basics.cpp"

+ 21
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/juce_module_info View File

@@ -0,0 +1,21 @@
{
"id": "juce_audio_basics",
"name": "JUCE audio and midi data classes",
"version": "2.0.32",
"description": "Classes for audio buffer manipulation, midi message handling, synthesis, etc",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",
"dependencies": [ { "id": "juce_core", "version": "matching" } ],
"include": "juce_audio_basics.h",
"compile": [ { "file": "juce_audio_basics.cpp", "target": "! xcode" },
{ "file": "juce_audio_basics.mm", "target": "xcode" } ],
"browse": [ "buffers/*",
"midi/*",
"effects/*",
"sources/*",
"synthesisers/*" ]
}

+ 290
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp View File

@@ -0,0 +1,290 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
namespace MidiBufferHelpers
{
inline int getEventTime (const void* const d) noexcept
{
return *static_cast <const int*> (d);
}
inline uint16 getEventDataSize (const void* const d) noexcept
{
return *reinterpret_cast <const uint16*> (static_cast <const char*> (d) + sizeof (int));
}
inline uint16 getEventTotalSize (const void* const d) noexcept
{
return getEventDataSize (d) + sizeof (int) + sizeof (uint16);
}
static int findActualEventLength (const uint8* const data, const int maxBytes) noexcept
{
unsigned int byte = (unsigned int) *data;
int size = 0;
if (byte == 0xf0 || byte == 0xf7)
{
const uint8* d = data + 1;
while (d < data + maxBytes)
if (*d++ == 0xf7)
break;
size = (int) (d - data);
}
else if (byte == 0xff)
{
int n;
const int bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n);
size = jmin (maxBytes, n + 2 + bytesLeft);
}
else if (byte >= 0x80)
{
size = jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte));
}
return size;
}
}
//==============================================================================
MidiBuffer::MidiBuffer() noexcept
: bytesUsed (0)
{
}
MidiBuffer::MidiBuffer (const MidiMessage& message) noexcept
: bytesUsed (0)
{
addEvent (message, 0);
}
MidiBuffer::MidiBuffer (const MidiBuffer& other) noexcept
: data (other.data),
bytesUsed (other.bytesUsed)
{
}
MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) noexcept
{
bytesUsed = other.bytesUsed;
data = other.data;
return *this;
}
void MidiBuffer::swapWith (MidiBuffer& other) noexcept
{
data.swapWith (other.data);
std::swap (bytesUsed, other.bytesUsed);
}
MidiBuffer::~MidiBuffer()
{
}
inline uint8* MidiBuffer::getData() const noexcept
{
return static_cast <uint8*> (data.getData());
}
void MidiBuffer::clear() noexcept
{
bytesUsed = 0;
}
void MidiBuffer::clear (const int startSample, const int numSamples)
{
uint8* const start = findEventAfter (getData(), startSample - 1);
uint8* const end = findEventAfter (start, startSample + numSamples - 1);
if (end > start)
{
const int bytesToMove = bytesUsed - (int) (end - getData());
if (bytesToMove > 0)
memmove (start, end, (size_t) bytesToMove);
bytesUsed -= (int) (end - start);
}
}
void MidiBuffer::addEvent (const MidiMessage& m, const int sampleNumber)
{
addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber);
}
void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const int sampleNumber)
{
const int numBytes = MidiBufferHelpers::findActualEventLength (static_cast <const uint8*> (newData), maxBytes);
if (numBytes > 0)
{
size_t spaceNeeded = (size_t) bytesUsed + (size_t) numBytes + sizeof (int) + sizeof (uint16);
data.ensureSize ((spaceNeeded + spaceNeeded / 2 + 8) & ~(size_t) 7);
uint8* d = findEventAfter (getData(), sampleNumber);
const int bytesToMove = bytesUsed - (int) (d - getData());
if (bytesToMove > 0)
memmove (d + numBytes + sizeof (int) + sizeof (uint16), d, (size_t) bytesToMove);
*reinterpret_cast <int*> (d) = sampleNumber;
d += sizeof (int);
*reinterpret_cast <uint16*> (d) = (uint16) numBytes;
d += sizeof (uint16);
memcpy (d, newData, (size_t) numBytes);
bytesUsed += sizeof (int) + sizeof (uint16) + (size_t) numBytes;
}
}
void MidiBuffer::addEvents (const MidiBuffer& otherBuffer,
const int startSample,
const int numSamples,
const int sampleDeltaToAdd)
{
Iterator i (otherBuffer);
i.setNextSamplePosition (startSample);
const uint8* eventData;
int eventSize, position;
while (i.getNextEvent (eventData, eventSize, position)
&& (position < startSample + numSamples || numSamples < 0))
{
addEvent (eventData, eventSize, position + sampleDeltaToAdd);
}
}
void MidiBuffer::ensureSize (size_t minimumNumBytes)
{
data.ensureSize (minimumNumBytes);
}
bool MidiBuffer::isEmpty() const noexcept
{
return bytesUsed == 0;
}
int MidiBuffer::getNumEvents() const noexcept
{
int n = 0;
const uint8* d = getData();
const uint8* const end = d + bytesUsed;
while (d < end)
{
d += MidiBufferHelpers::getEventTotalSize (d);
++n;
}
return n;
}
int MidiBuffer::getFirstEventTime() const noexcept
{
return bytesUsed > 0 ? MidiBufferHelpers::getEventTime (data.getData()) : 0;
}
int MidiBuffer::getLastEventTime() const noexcept
{
if (bytesUsed == 0)
return 0;
const uint8* d = getData();
const uint8* const endData = d + bytesUsed;
for (;;)
{
const uint8* const nextOne = d + MidiBufferHelpers::getEventTotalSize (d);
if (nextOne >= endData)
return MidiBufferHelpers::getEventTime (d);
d = nextOne;
}
}
uint8* MidiBuffer::findEventAfter (uint8* d, const int samplePosition) const noexcept
{
const uint8* const endData = getData() + bytesUsed;
while (d < endData && MidiBufferHelpers::getEventTime (d) <= samplePosition)
d += MidiBufferHelpers::getEventTotalSize (d);
return d;
}
//==============================================================================
MidiBuffer::Iterator::Iterator (const MidiBuffer& buffer_) noexcept
: buffer (buffer_),
data (buffer_.getData())
{
}
MidiBuffer::Iterator::~Iterator() noexcept
{
}
//==============================================================================
void MidiBuffer::Iterator::setNextSamplePosition (const int samplePosition) noexcept
{
data = buffer.getData();
const uint8* dataEnd = data + buffer.bytesUsed;
while (data < dataEnd && MidiBufferHelpers::getEventTime (data) < samplePosition)
data += MidiBufferHelpers::getEventTotalSize (data);
}
bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, int& numBytes, int& samplePosition) noexcept
{
if (data >= buffer.getData() + buffer.bytesUsed)
return false;
samplePosition = MidiBufferHelpers::getEventTime (data);
numBytes = MidiBufferHelpers::getEventDataSize (data);
data += sizeof (int) + sizeof (uint16);
midiData = data;
data += numBytes;
return true;
}
bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePosition) noexcept
{
if (data >= buffer.getData() + buffer.bytesUsed)
return false;
samplePosition = MidiBufferHelpers::getEventTime (data);
const int numBytes = MidiBufferHelpers::getEventDataSize (data);
data += sizeof (int) + sizeof (uint16);
result = MidiMessage (data, numBytes, samplePosition);
data += numBytes;
return true;
}

+ 241
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h View File

@@ -0,0 +1,241 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIBUFFER_JUCEHEADER__
#define __JUCE_MIDIBUFFER_JUCEHEADER__
#include "juce_MidiMessage.h"
//==============================================================================
/**
Holds a sequence of time-stamped midi events.
Analogous to the AudioSampleBuffer, this holds a set of midi events with
integer time-stamps. The buffer is kept sorted in order of the time-stamps.
If you're working with a sequence of midi events that may need to be manipulated
or read/written to a midi file, then MidiMessageSequence is probably a more
appropriate container. MidiBuffer is designed for lower-level streams of raw
midi data.
@see MidiMessage
*/
class JUCE_API MidiBuffer
{
public:
//==============================================================================
/** Creates an empty MidiBuffer. */
MidiBuffer() noexcept;
/** Creates a MidiBuffer containing a single midi message. */
explicit MidiBuffer (const MidiMessage& message) noexcept;
/** Creates a copy of another MidiBuffer. */
MidiBuffer (const MidiBuffer& other) noexcept;
/** Makes a copy of another MidiBuffer. */
MidiBuffer& operator= (const MidiBuffer& other) noexcept;
/** Destructor */
~MidiBuffer();
//==============================================================================
/** Removes all events from the buffer. */
void clear() noexcept;
/** Removes all events between two times from the buffer.
All events for which (start <= event position < start + numSamples) will
be removed.
*/
void clear (int start, int numSamples);
/** Returns true if the buffer is empty.
To actually retrieve the events, use a MidiBuffer::Iterator object
*/
bool isEmpty() const noexcept;
/** Counts the number of events in the buffer.
This is actually quite a slow operation, as it has to iterate through all
the events, so you might prefer to call isEmpty() if that's all you need
to know.
*/
int getNumEvents() const noexcept;
/** Adds an event to the buffer.
The sample number will be used to determine the position of the event in
the buffer, which is always kept sorted. The MidiMessage's timestamp is
ignored.
If an event is added whose sample position is the same as one or more events
already in the buffer, the new event will be placed after the existing ones.
To retrieve events, use a MidiBuffer::Iterator object
*/
void addEvent (const MidiMessage& midiMessage, int sampleNumber);
/** Adds an event to the buffer from raw midi data.
The sample number will be used to determine the position of the event in
the buffer, which is always kept sorted.
If an event is added whose sample position is the same as one or more events
already in the buffer, the new event will be placed after the existing ones.
The event data will be inspected to calculate the number of bytes in length that
the midi event really takes up, so maxBytesOfMidiData may be longer than the data
that actually gets stored. E.g. if you pass in a note-on and a length of 4 bytes,
it'll actually only store 3 bytes. If the midi data is invalid, it might not
add an event at all.
To retrieve events, use a MidiBuffer::Iterator object
*/
void addEvent (const void* rawMidiData,
int maxBytesOfMidiData,
int sampleNumber);
/** Adds some events from another buffer to this one.
@param otherBuffer the buffer containing the events you want to add
@param startSample the lowest sample number in the source buffer for which
events should be added. Any source events whose timestamp is
less than this will be ignored
@param numSamples the valid range of samples from the source buffer for which
events should be added - i.e. events in the source buffer whose
timestamp is greater than or equal to (startSample + numSamples)
will be ignored. If this value is less than 0, all events after
startSample will be taken.
@param sampleDeltaToAdd a value which will be added to the source timestamps of the events
that are added to this buffer
*/
void addEvents (const MidiBuffer& otherBuffer,
int startSample,
int numSamples,
int sampleDeltaToAdd);
/** Returns the sample number of the first event in the buffer.
If the buffer's empty, this will just return 0.
*/
int getFirstEventTime() const noexcept;
/** Returns the sample number of the last event in the buffer.
If the buffer's empty, this will just return 0.
*/
int getLastEventTime() const noexcept;
//==============================================================================
/** Exchanges the contents of this buffer with another one.
This is a quick operation, because no memory allocating or copying is done, it
just swaps the internal state of the two buffers.
*/
void swapWith (MidiBuffer& other) noexcept;
/** Preallocates some memory for the buffer to use.
This helps to avoid needing to reallocate space when the buffer has messages
added to it.
*/
void ensureSize (size_t minimumNumBytes);
//==============================================================================
/**
Used to iterate through the events in a MidiBuffer.
Note that altering the buffer while an iterator is using it isn't a
safe operation.
@see MidiBuffer
*/
class JUCE_API Iterator
{
public:
//==============================================================================
/** Creates an Iterator for this MidiBuffer. */
Iterator (const MidiBuffer& buffer) noexcept;
/** Destructor. */
~Iterator() noexcept;
//==============================================================================
/** Repositions the iterator so that the next event retrieved will be the first
one whose sample position is at greater than or equal to the given position.
*/
void setNextSamplePosition (int samplePosition) noexcept;
/** Retrieves a copy of the next event from the buffer.
@param result on return, this will be the message (the MidiMessage's timestamp
is not set)
@param samplePosition on return, this will be the position of the event
@returns true if an event was found, or false if the iterator has reached
the end of the buffer
*/
bool getNextEvent (MidiMessage& result,
int& samplePosition) noexcept;
/** Retrieves the next event from the buffer.
@param midiData on return, this pointer will be set to a block of data containing
the midi message. Note that to make it fast, this is a pointer
directly into the MidiBuffer's internal data, so is only valid
temporarily until the MidiBuffer is altered.
@param numBytesOfMidiData on return, this is the number of bytes of data used by the
midi message
@param samplePosition on return, this will be the position of the event
@returns true if an event was found, or false if the iterator has reached
the end of the buffer
*/
bool getNextEvent (const uint8* &midiData,
int& numBytesOfMidiData,
int& samplePosition) noexcept;
private:
//==============================================================================
const MidiBuffer& buffer;
const uint8* data;
JUCE_DECLARE_NON_COPYABLE (Iterator)
};
private:
//==============================================================================
friend class MidiBuffer::Iterator;
MemoryBlock data;
int bytesUsed;
uint8* getData() const noexcept;
uint8* findEventAfter (uint8*, int samplePosition) const noexcept;
JUCE_LEAK_DETECTOR (MidiBuffer)
};
#endif // __JUCE_MIDIBUFFER_JUCEHEADER__

+ 425
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.cpp View File

@@ -0,0 +1,425 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
namespace MidiFileHelpers
{
static void writeVariableLengthInt (OutputStream& out, unsigned int v)
{
unsigned int buffer = v & 0x7f;
while ((v >>= 7) != 0)
{
buffer <<= 8;
buffer |= ((v & 0x7f) | 0x80);
}
for (;;)
{
out.writeByte ((char) buffer);
if (buffer & 0x80)
buffer >>= 8;
else
break;
}
}
static bool parseMidiHeader (const uint8* &data, short& timeFormat, short& fileType, short& numberOfTracks) noexcept
{
unsigned int ch = ByteOrder::bigEndianInt (data);
data += 4;
if (ch != ByteOrder::bigEndianInt ("MThd"))
{
bool ok = false;
if (ch == ByteOrder::bigEndianInt ("RIFF"))
{
for (int i = 0; i < 8; ++i)
{
ch = ByteOrder::bigEndianInt (data);
data += 4;
if (ch == ByteOrder::bigEndianInt ("MThd"))
{
ok = true;
break;
}
}
}
if (! ok)
return false;
}
unsigned int bytesRemaining = ByteOrder::bigEndianInt (data);
data += 4;
fileType = (short) ByteOrder::bigEndianShort (data);
data += 2;
numberOfTracks = (short) ByteOrder::bigEndianShort (data);
data += 2;
timeFormat = (short) ByteOrder::bigEndianShort (data);
data += 2;
bytesRemaining -= 6;
data += bytesRemaining;
return true;
}
static double convertTicksToSeconds (const double time,
const MidiMessageSequence& tempoEvents,
const int timeFormat)
{
if (timeFormat < 0)
return time / (-(timeFormat >> 8) * (timeFormat & 0xff));
double lastTime = 0.0, correctedTime = 0.0;
const double tickLen = 1.0 / (timeFormat & 0x7fff);
double secsPerTick = 0.5 * tickLen;
const int numEvents = tempoEvents.getNumEvents();
for (int i = 0; i < numEvents; ++i)
{
const MidiMessage& m = tempoEvents.getEventPointer(i)->message;
const double eventTime = m.getTimeStamp();
if (eventTime >= time)
break;
correctedTime += (eventTime - lastTime) * secsPerTick;
lastTime = eventTime;
if (m.isTempoMetaEvent())
secsPerTick = tickLen * m.getTempoSecondsPerQuarterNote();
while (i + 1 < numEvents)
{
const MidiMessage& m2 = tempoEvents.getEventPointer(i + 1)->message;
if (m2.getTimeStamp() != eventTime)
break;
if (m2.isTempoMetaEvent())
secsPerTick = tickLen * m2.getTempoSecondsPerQuarterNote();
++i;
}
}
return correctedTime + (time - lastTime) * secsPerTick;
}
// a comparator that puts all the note-offs before note-ons that have the same time
struct Sorter
{
static int compareElements (const MidiMessageSequence::MidiEventHolder* const first,
const MidiMessageSequence::MidiEventHolder* const second) noexcept
{
const double diff = (first->message.getTimeStamp() - second->message.getTimeStamp());
if (diff > 0) return 1;
if (diff < 0) return -1;
if (first->message.isNoteOff() && second->message.isNoteOn()) return -1;
if (first->message.isNoteOn() && second->message.isNoteOff()) return 1;
return 0;
}
};
}
//==============================================================================
MidiFile::MidiFile()
: timeFormat ((short) (unsigned short) 0xe728)
{
}
MidiFile::~MidiFile()
{
}
void MidiFile::clear()
{
tracks.clear();
}
//==============================================================================
int MidiFile::getNumTracks() const noexcept
{
return tracks.size();
}
const MidiMessageSequence* MidiFile::getTrack (const int index) const noexcept
{
return tracks [index];
}
void MidiFile::addTrack (const MidiMessageSequence& trackSequence)
{
tracks.add (new MidiMessageSequence (trackSequence));
}
//==============================================================================
short MidiFile::getTimeFormat() const noexcept
{
return timeFormat;
}
void MidiFile::setTicksPerQuarterNote (const int ticks) noexcept
{
timeFormat = (short) ticks;
}
void MidiFile::setSmpteTimeFormat (const int framesPerSecond,
const int subframeResolution) noexcept
{
timeFormat = (short) (((-framesPerSecond) << 8) | subframeResolution);
}
//==============================================================================
void MidiFile::findAllTempoEvents (MidiMessageSequence& tempoChangeEvents) const
{
for (int i = tracks.size(); --i >= 0;)
{
const int numEvents = tracks.getUnchecked(i)->getNumEvents();
for (int j = 0; j < numEvents; ++j)
{
const MidiMessage& m = tracks.getUnchecked(i)->getEventPointer (j)->message;
if (m.isTempoMetaEvent())
tempoChangeEvents.addEvent (m);
}
}
}
void MidiFile::findAllTimeSigEvents (MidiMessageSequence& timeSigEvents) const
{
for (int i = tracks.size(); --i >= 0;)
{
const int numEvents = tracks.getUnchecked(i)->getNumEvents();
for (int j = 0; j < numEvents; ++j)
{
const MidiMessage& m = tracks.getUnchecked(i)->getEventPointer (j)->message;
if (m.isTimeSignatureMetaEvent())
timeSigEvents.addEvent (m);
}
}
}
double MidiFile::getLastTimestamp() const
{
double t = 0.0;
for (int i = tracks.size(); --i >= 0;)
t = jmax (t, tracks.getUnchecked(i)->getEndTime());
return t;
}
//==============================================================================
bool MidiFile::readFrom (InputStream& sourceStream)
{
clear();
MemoryBlock data;
const int maxSensibleMidiFileSize = 2 * 1024 * 1024;
// (put a sanity-check on the file size, as midi files are generally small)
if (sourceStream.readIntoMemoryBlock (data, maxSensibleMidiFileSize))
{
size_t size = data.getSize();
const uint8* d = static_cast <const uint8*> (data.getData());
short fileType, expectedTracks;
if (size > 16 && MidiFileHelpers::parseMidiHeader (d, timeFormat, fileType, expectedTracks))
{
size -= (size_t) (d - static_cast <const uint8*> (data.getData()));
int track = 0;
while (size > 0 && track < expectedTracks)
{
const int chunkType = (int) ByteOrder::bigEndianInt (d);
d += 4;
const int chunkSize = (int) ByteOrder::bigEndianInt (d);
d += 4;
if (chunkSize <= 0)
break;
if (chunkType == (int) ByteOrder::bigEndianInt ("MTrk"))
readNextTrack (d, chunkSize);
size -= (size_t) chunkSize + 8;
d += chunkSize;
++track;
}
return true;
}
}
return false;
}
void MidiFile::readNextTrack (const uint8* data, int size)
{
double time = 0;
uint8 lastStatusByte = 0;
MidiMessageSequence result;
while (size > 0)
{
int bytesUsed;
const int delay = MidiMessage::readVariableLengthVal (data, bytesUsed);
data += bytesUsed;
size -= bytesUsed;
time += delay;
int messSize = 0;
const MidiMessage mm (data, size, messSize, lastStatusByte, time);
if (messSize <= 0)
break;
size -= messSize;
data += messSize;
result.addEvent (mm);
const uint8 firstByte = *(mm.getRawData());
if ((firstByte & 0xf0) != 0xf0)
lastStatusByte = firstByte;
}
// use a sort that puts all the note-offs before note-ons that have the same time
MidiFileHelpers::Sorter sorter;
result.list.sort (sorter, true);
addTrack (result);
tracks.getLast()->updateMatchedPairs();
}
//==============================================================================
void MidiFile::convertTimestampTicksToSeconds()
{
MidiMessageSequence tempoEvents;
findAllTempoEvents (tempoEvents);
findAllTimeSigEvents (tempoEvents);
if (timeFormat != 0)
{
for (int i = 0; i < tracks.size(); ++i)
{
const MidiMessageSequence& ms = *tracks.getUnchecked(i);
for (int j = ms.getNumEvents(); --j >= 0;)
{
MidiMessage& m = ms.getEventPointer(j)->message;
m.setTimeStamp (MidiFileHelpers::convertTicksToSeconds (m.getTimeStamp(),
tempoEvents,
timeFormat));
}
}
}
}
//==============================================================================
bool MidiFile::writeTo (OutputStream& out)
{
out.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MThd"));
out.writeIntBigEndian (6);
out.writeShortBigEndian (1); // type
out.writeShortBigEndian ((short) tracks.size());
out.writeShortBigEndian (timeFormat);
for (int i = 0; i < tracks.size(); ++i)
writeTrack (out, i);
out.flush();
return true;
}
void MidiFile::writeTrack (OutputStream& mainOut, const int trackNum)
{
MemoryOutputStream out;
const MidiMessageSequence& ms = *tracks.getUnchecked (trackNum);
int lastTick = 0;
uint8 lastStatusByte = 0;
for (int i = 0; i < ms.getNumEvents(); ++i)
{
const MidiMessage& mm = ms.getEventPointer(i)->message;
if (! mm.isEndOfTrackMetaEvent())
{
const int tick = roundToInt (mm.getTimeStamp());
const int delta = jmax (0, tick - lastTick);
MidiFileHelpers::writeVariableLengthInt (out, (uint32) delta);
lastTick = tick;
const uint8* data = mm.getRawData();
int dataSize = mm.getRawDataSize();
const uint8 statusByte = data[0];
if (statusByte == lastStatusByte
&& (statusByte & 0xf0) != 0xf0
&& dataSize > 1
&& i > 0)
{
++data;
--dataSize;
}
else if (statusByte == 0xf0) // Write sysex message with length bytes.
{
out.writeByte ((char) statusByte);
++data;
--dataSize;
MidiFileHelpers::writeVariableLengthInt (out, (uint32) dataSize);
}
out.write (data, dataSize);
lastStatusByte = statusByte;
}
}
{
out.writeByte (0); // (tick delta)
const MidiMessage m (MidiMessage::endOfTrack());
out.write (m.getRawData(), m.getRawDataSize());
}
mainOut.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MTrk"));
mainOut.writeIntBigEndian ((int) out.getDataSize());
mainOut << out;
}

+ 187
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.h View File

@@ -0,0 +1,187 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIFILE_JUCEHEADER__
#define __JUCE_MIDIFILE_JUCEHEADER__
#include "juce_MidiMessageSequence.h"
//==============================================================================
/**
Reads/writes standard midi format files.
To read a midi file, create a MidiFile object and call its readFrom() method. You
can then get the individual midi tracks from it using the getTrack() method.
To write a file, create a MidiFile object, add some MidiMessageSequence objects
to it using the addTrack() method, and then call its writeTo() method to stream
it out.
@see MidiMessageSequence
*/
class JUCE_API MidiFile
{
public:
//==============================================================================
/** Creates an empty MidiFile object.
*/
MidiFile();
/** Destructor. */
~MidiFile();
//==============================================================================
/** Returns the number of tracks in the file.
@see getTrack, addTrack
*/
int getNumTracks() const noexcept;
/** Returns a pointer to one of the tracks in the file.
@returns a pointer to the track, or nullptr if the index is out-of-range
@see getNumTracks, addTrack
*/
const MidiMessageSequence* getTrack (int index) const noexcept;
/** Adds a midi track to the file.
This will make its own internal copy of the sequence that is passed-in.
@see getNumTracks, getTrack
*/
void addTrack (const MidiMessageSequence& trackSequence);
/** Removes all midi tracks from the file.
@see getNumTracks
*/
void clear();
/** Returns the raw time format code that will be written to a stream.
After reading a midi file, this method will return the time-format that
was read from the file's header. It can be changed using the setTicksPerQuarterNote()
or setSmpteTimeFormat() methods.
If the value returned is positive, it indicates the number of midi ticks
per quarter-note - see setTicksPerQuarterNote().
It it's negative, the upper byte indicates the frames-per-second (but negative), and
the lower byte is the number of ticks per frame - see setSmpteTimeFormat().
*/
short getTimeFormat() const noexcept;
/** Sets the time format to use when this file is written to a stream.
If this is called, the file will be written as bars/beats using the
specified resolution, rather than SMPTE absolute times, as would be
used if setSmpteTimeFormat() had been called instead.
@param ticksPerQuarterNote e.g. 96, 960
@see setSmpteTimeFormat
*/
void setTicksPerQuarterNote (int ticksPerQuarterNote) noexcept;
/** Sets the time format to use when this file is written to a stream.
If this is called, the file will be written using absolute times, rather
than bars/beats as would be the case if setTicksPerBeat() had been called
instead.
@param framesPerSecond must be 24, 25, 29 or 30
@param subframeResolution the sub-second resolution, e.g. 4 (midi time code),
8, 10, 80 (SMPTE bit resolution), or 100. For millisecond
timing, setSmpteTimeFormat (25, 40)
@see setTicksPerBeat
*/
void setSmpteTimeFormat (int framesPerSecond,
int subframeResolution) noexcept;
//==============================================================================
/** Makes a list of all the tempo-change meta-events from all tracks in the midi file.
Useful for finding the positions of all the tempo changes in a file.
@param tempoChangeEvents a list to which all the events will be added
*/
void findAllTempoEvents (MidiMessageSequence& tempoChangeEvents) const;
/** Makes a list of all the time-signature meta-events from all tracks in the midi file.
Useful for finding the positions of all the tempo changes in a file.
@param timeSigEvents a list to which all the events will be added
*/
void findAllTimeSigEvents (MidiMessageSequence& timeSigEvents) const;
/** Returns the latest timestamp in any of the tracks.
(Useful for finding the length of the file).
*/
double getLastTimestamp() const;
//==============================================================================
/** Reads a midi file format stream.
After calling this, you can get the tracks that were read from the file by using the
getNumTracks() and getTrack() methods.
The timestamps of the midi events in the tracks will represent their positions in
terms of midi ticks. To convert them to seconds, use the convertTimestampTicksToSeconds()
method.
@returns true if the stream was read successfully
*/
bool readFrom (InputStream& sourceStream);
/** Writes the midi tracks as a standard midi file.
@returns true if the operation succeeded.
*/
bool writeTo (OutputStream& destStream);
/** Converts the timestamp of all the midi events from midi ticks to seconds.
This will use the midi time format and tempo/time signature info in the
tracks to convert all the timestamps to absolute values in seconds.
*/
void convertTimestampTicksToSeconds();
private:
//==============================================================================
OwnedArray <MidiMessageSequence> tracks;
short timeFormat;
void readNextTrack (const uint8* data, int size);
void writeTrack (OutputStream& mainOut, int trackNum);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiFile)
};
#endif // __JUCE_MIDIFILE_JUCEHEADER__

+ 184
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp View File

@@ -0,0 +1,184 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
MidiKeyboardState::MidiKeyboardState()
{
zerostruct (noteStates);
}
MidiKeyboardState::~MidiKeyboardState()
{
}
//==============================================================================
void MidiKeyboardState::reset()
{
const ScopedLock sl (lock);
zerostruct (noteStates);
eventsToAdd.clear();
}
bool MidiKeyboardState::isNoteOn (const int midiChannel, const int n) const noexcept
{
jassert (midiChannel >= 0 && midiChannel <= 16);
return isPositiveAndBelow (n, (int) 128)
&& (noteStates[n] & (1 << (midiChannel - 1))) != 0;
}
bool MidiKeyboardState::isNoteOnForChannels (const int midiChannelMask, const int n) const noexcept
{
return isPositiveAndBelow (n, (int) 128)
&& (noteStates[n] & midiChannelMask) != 0;
}
void MidiKeyboardState::noteOn (const int midiChannel, const int midiNoteNumber, const float velocity)
{
jassert (midiChannel >= 0 && midiChannel <= 16);
jassert (isPositiveAndBelow (midiNoteNumber, (int) 128));
const ScopedLock sl (lock);
if (isPositiveAndBelow (midiNoteNumber, (int) 128))
{
const int timeNow = (int) Time::getMillisecondCounter();
eventsToAdd.addEvent (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity), timeNow);
eventsToAdd.clear (0, timeNow - 500);
noteOnInternal (midiChannel, midiNoteNumber, velocity);
}
}
void MidiKeyboardState::noteOnInternal (const int midiChannel, const int midiNoteNumber, const float velocity)
{
if (isPositiveAndBelow (midiNoteNumber, (int) 128))
{
noteStates [midiNoteNumber] |= (1 << (midiChannel - 1));
for (int i = listeners.size(); --i >= 0;)
listeners.getUnchecked(i)->handleNoteOn (this, midiChannel, midiNoteNumber, velocity);
}
}
void MidiKeyboardState::noteOff (const int midiChannel, const int midiNoteNumber)
{
const ScopedLock sl (lock);
if (isNoteOn (midiChannel, midiNoteNumber))
{
const int timeNow = (int) Time::getMillisecondCounter();
eventsToAdd.addEvent (MidiMessage::noteOff (midiChannel, midiNoteNumber), timeNow);
eventsToAdd.clear (0, timeNow - 500);
noteOffInternal (midiChannel, midiNoteNumber);
}
}
void MidiKeyboardState::noteOffInternal (const int midiChannel, const int midiNoteNumber)
{
if (isNoteOn (midiChannel, midiNoteNumber))
{
noteStates [midiNoteNumber] &= ~(1 << (midiChannel - 1));
for (int i = listeners.size(); --i >= 0;)
listeners.getUnchecked(i)->handleNoteOff (this, midiChannel, midiNoteNumber);
}
}
void MidiKeyboardState::allNotesOff (const int midiChannel)
{
const ScopedLock sl (lock);
if (midiChannel <= 0)
{
for (int i = 1; i <= 16; ++i)
allNotesOff (i);
}
else
{
for (int i = 0; i < 128; ++i)
noteOff (midiChannel, i);
}
}
void MidiKeyboardState::processNextMidiEvent (const MidiMessage& message)
{
if (message.isNoteOn())
{
noteOnInternal (message.getChannel(), message.getNoteNumber(), message.getFloatVelocity());
}
else if (message.isNoteOff())
{
noteOffInternal (message.getChannel(), message.getNoteNumber());
}
else if (message.isAllNotesOff())
{
for (int i = 0; i < 128; ++i)
noteOffInternal (message.getChannel(), i);
}
}
void MidiKeyboardState::processNextMidiBuffer (MidiBuffer& buffer,
const int startSample,
const int numSamples,
const bool injectIndirectEvents)
{
MidiBuffer::Iterator i (buffer);
MidiMessage message (0xf4, 0.0);
int time;
const ScopedLock sl (lock);
while (i.getNextEvent (message, time))
processNextMidiEvent (message);
if (injectIndirectEvents)
{
MidiBuffer::Iterator i2 (eventsToAdd);
const int firstEventToAdd = eventsToAdd.getFirstEventTime();
const double scaleFactor = numSamples / (double) (eventsToAdd.getLastEventTime() + 1 - firstEventToAdd);
while (i2.getNextEvent (message, time))
{
const int pos = jlimit (0, numSamples - 1, roundToInt ((time - firstEventToAdd) * scaleFactor));
buffer.addEvent (message, startSample + pos);
}
}
eventsToAdd.clear();
}
//==============================================================================
void MidiKeyboardState::addListener (MidiKeyboardStateListener* const listener)
{
const ScopedLock sl (lock);
listeners.addIfNotAlreadyThere (listener);
}
void MidiKeyboardState::removeListener (MidiKeyboardStateListener* const listener)
{
const ScopedLock sl (lock);
listeners.removeFirstMatchingValue (listener);
}

+ 209
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h View File

@@ -0,0 +1,209 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIKEYBOARDSTATE_JUCEHEADER__
#define __JUCE_MIDIKEYBOARDSTATE_JUCEHEADER__
#include "juce_MidiBuffer.h"
class MidiKeyboardState;
//==============================================================================
/**
Receives events from a MidiKeyboardState object.
@see MidiKeyboardState
*/
class JUCE_API MidiKeyboardStateListener
{
public:
//==============================================================================
MidiKeyboardStateListener() noexcept {}
virtual ~MidiKeyboardStateListener() {}
//==============================================================================
/** Called when one of the MidiKeyboardState's keys is pressed.
This will be called synchronously when the state is either processing a
buffer in its MidiKeyboardState::processNextMidiBuffer() method, or
when a note is being played with its MidiKeyboardState::noteOn() method.
Note that this callback could happen from an audio callback thread, so be
careful not to block, and avoid any UI activity in the callback.
*/
virtual void handleNoteOn (MidiKeyboardState* source,
int midiChannel, int midiNoteNumber, float velocity) = 0;
/** Called when one of the MidiKeyboardState's keys is released.
This will be called synchronously when the state is either processing a
buffer in its MidiKeyboardState::processNextMidiBuffer() method, or
when a note is being played with its MidiKeyboardState::noteOff() method.
Note that this callback could happen from an audio callback thread, so be
careful not to block, and avoid any UI activity in the callback.
*/
virtual void handleNoteOff (MidiKeyboardState* source,
int midiChannel, int midiNoteNumber) = 0;
};
//==============================================================================
/**
Represents a piano keyboard, keeping track of which keys are currently pressed.
This object can parse a stream of midi events, using them to update its idea
of which keys are pressed for each individiual midi channel.
When keys go up or down, it can broadcast these events to listener objects.
It also allows key up/down events to be triggered with its noteOn() and noteOff()
methods, and midi messages for these events will be merged into the
midi stream that gets processed by processNextMidiBuffer().
*/
class JUCE_API MidiKeyboardState
{
public:
//==============================================================================
MidiKeyboardState();
~MidiKeyboardState();
//==============================================================================
/** Resets the state of the object.
All internal data for all the channels is reset, but no events are sent as a
result.
If you want to release any keys that are currently down, and to send out note-up
midi messages for this, use the allNotesOff() method instead.
*/
void reset();
/** Returns true if the given midi key is currently held down for the given midi channel.
The channel number must be between 1 and 16. If you want to see if any notes are
on for a range of channels, use the isNoteOnForChannels() method.
*/
bool isNoteOn (int midiChannel, int midiNoteNumber) const noexcept;
/** Returns true if the given midi key is currently held down on any of a set of midi channels.
The channel mask has a bit set for each midi channel you want to test for - bit
0 = midi channel 1, bit 1 = midi channel 2, etc.
If a note is on for at least one of the specified channels, this returns true.
*/
bool isNoteOnForChannels (int midiChannelMask, int midiNoteNumber) const noexcept;
/** Turns a specified note on.
This will cause a suitable midi note-on event to be injected into the midi buffer during the
next call to processNextMidiBuffer().
It will also trigger a synchronous callback to the listeners to tell them that the key has
gone down.
*/
void noteOn (int midiChannel, int midiNoteNumber, float velocity);
/** Turns a specified note off.
This will cause a suitable midi note-off event to be injected into the midi buffer during the
next call to processNextMidiBuffer().
It will also trigger a synchronous callback to the listeners to tell them that the key has
gone up.
But if the note isn't acutally down for the given channel, this method will in fact do nothing.
*/
void noteOff (int midiChannel, int midiNoteNumber);
/** This will turn off any currently-down notes for the given midi channel.
If you pass 0 for the midi channel, it will in fact turn off all notes on all channels.
Calling this method will make calls to noteOff(), so can trigger synchronous callbacks
and events being added to the midi stream.
*/
void allNotesOff (int midiChannel);
//==============================================================================
/** Looks at a key-up/down event and uses it to update the state of this object.
To process a buffer full of midi messages, use the processNextMidiBuffer() method
instead.
*/
void processNextMidiEvent (const MidiMessage& message);
/** Scans a midi stream for up/down events and adds its own events to it.
This will look for any up/down events and use them to update the internal state,
synchronously making suitable callbacks to the listeners.
If injectIndirectEvents is true, then midi events to produce the recent noteOn()
and noteOff() calls will be added into the buffer.
Only the section of the buffer whose timestamps are between startSample and
(startSample + numSamples) will be affected, and any events added will be placed
between these times.
If you're going to use this method, you'll need to keep calling it regularly for
it to work satisfactorily.
To process a single midi event at a time, use the processNextMidiEvent() method
instead.
*/
void processNextMidiBuffer (MidiBuffer& buffer,
int startSample,
int numSamples,
bool injectIndirectEvents);
//==============================================================================
/** Registers a listener for callbacks when keys go up or down.
@see removeListener
*/
void addListener (MidiKeyboardStateListener* listener);
/** Deregisters a listener.
@see addListener
*/
void removeListener (MidiKeyboardStateListener* listener);
private:
//==============================================================================
CriticalSection lock;
uint16 noteStates [128];
MidiBuffer eventsToAdd;
Array <MidiKeyboardStateListener*> listeners;
void noteOnInternal (int midiChannel, int midiNoteNumber, float velocity);
void noteOffInternal (int midiChannel, int midiNoteNumber);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiKeyboardState)
};
#endif // __JUCE_MIDIKEYBOARDSTATE_JUCEHEADER__

+ 1049
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
File diff suppressed because it is too large
View File


+ 940
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.h View File

@@ -0,0 +1,940 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIMESSAGE_JUCEHEADER__
#define __JUCE_MIDIMESSAGE_JUCEHEADER__
//==============================================================================
/**
Encapsulates a MIDI message.
@see MidiMessageSequence, MidiOutput, MidiInput
*/
class JUCE_API MidiMessage
{
public:
//==============================================================================
/** Creates a 3-byte short midi message.
@param byte1 message byte 1
@param byte2 message byte 2
@param byte3 message byte 3
@param timeStamp the time to give the midi message - this value doesn't
use any particular units, so will be application-specific
*/
MidiMessage (int byte1, int byte2, int byte3, double timeStamp = 0) noexcept;
/** Creates a 2-byte short midi message.
@param byte1 message byte 1
@param byte2 message byte 2
@param timeStamp the time to give the midi message - this value doesn't
use any particular units, so will be application-specific
*/
MidiMessage (int byte1, int byte2, double timeStamp = 0) noexcept;
/** Creates a 1-byte short midi message.
@param byte1 message byte 1
@param timeStamp the time to give the midi message - this value doesn't
use any particular units, so will be application-specific
*/
MidiMessage (int byte1, double timeStamp = 0) noexcept;
/** Creates a midi message from a block of data. */
MidiMessage (const void* data, int numBytes, double timeStamp = 0);
/** Reads the next midi message from some data.
This will read as many bytes from a data stream as it needs to make a
complete message, and will return the number of bytes it used. This lets
you read a sequence of midi messages from a file or stream.
@param data the data to read from
@param maxBytesToUse the maximum number of bytes it's allowed to read
@param numBytesUsed returns the number of bytes that were actually needed
@param lastStatusByte in a sequence of midi messages, the initial byte
can be dropped from a message if it's the same as the
first byte of the previous message, so this lets you
supply the byte to use if the first byte of the message
has in fact been dropped.
@param timeStamp the time to give the midi message - this value doesn't
use any particular units, so will be application-specific
*/
MidiMessage (const void* data, int maxBytesToUse,
int& numBytesUsed, uint8 lastStatusByte,
double timeStamp = 0);
/** Creates an active-sense message.
Since the MidiMessage has to contain a valid message, this default constructor
just initialises it with an empty sysex message.
*/
MidiMessage() noexcept;
/** Creates a copy of another midi message. */
MidiMessage (const MidiMessage& other);
/** Creates a copy of another midi message, with a different timestamp. */
MidiMessage (const MidiMessage& other, double newTimeStamp);
/** Destructor. */
~MidiMessage();
/** Copies this message from another one. */
MidiMessage& operator= (const MidiMessage& other);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
MidiMessage (MidiMessage&& other) noexcept;
MidiMessage& operator= (MidiMessage&& other) noexcept;
#endif
//==============================================================================
/** Returns a pointer to the raw midi data.
@see getRawDataSize
*/
uint8* getRawData() const noexcept { return data; }
/** Returns the number of bytes of data in the message.
@see getRawData
*/
int getRawDataSize() const noexcept { return size; }
//==============================================================================
/** Returns the timestamp associated with this message.
The exact meaning of this time and its units will vary, as messages are used in
a variety of different contexts.
If you're getting the message from a midi file, this could be a time in seconds, or
a number of ticks - see MidiFile::convertTimestampTicksToSeconds().
If the message is being used in a MidiBuffer, it might indicate the number of
audio samples from the start of the buffer.
If the message was created by a MidiInput, see MidiInputCallback::handleIncomingMidiMessage()
for details of the way that it initialises this value.
@see setTimeStamp, addToTimeStamp
*/
double getTimeStamp() const noexcept { return timeStamp; }
/** Changes the message's associated timestamp.
The units for the timestamp will be application-specific - see the notes for getTimeStamp().
@see addToTimeStamp, getTimeStamp
*/
void setTimeStamp (double newTimestamp) noexcept { timeStamp = newTimestamp; }
/** Adds a value to the message's timestamp.
The units for the timestamp will be application-specific.
*/
void addToTimeStamp (double delta) noexcept { timeStamp += delta; }
//==============================================================================
/** Returns the midi channel associated with the message.
@returns a value 1 to 16 if the message has a channel, or 0 if it hasn't (e.g.
if it's a sysex)
@see isForChannel, setChannel
*/
int getChannel() const noexcept;
/** Returns true if the message applies to the given midi channel.
@param channelNumber the channel number to look for, in the range 1 to 16
@see getChannel, setChannel
*/
bool isForChannel (int channelNumber) const noexcept;
/** Changes the message's midi channel.
This won't do anything for non-channel messages like sysexes.
@param newChannelNumber the channel number to change it to, in the range 1 to 16
*/
void setChannel (int newChannelNumber) noexcept;
//==============================================================================
/** Returns true if this is a system-exclusive message.
*/
bool isSysEx() const noexcept;
/** Returns a pointer to the sysex data inside the message.
If this event isn't a sysex event, it'll return 0.
@see getSysExDataSize
*/
const uint8* getSysExData() const noexcept;
/** Returns the size of the sysex data.
This value excludes the 0xf0 header byte and the 0xf7 at the end.
@see getSysExData
*/
int getSysExDataSize() const noexcept;
//==============================================================================
/** Returns true if this message is a 'key-down' event.
@param returnTrueForVelocity0 if true, then if this event is a note-on with
velocity 0, it will still be considered to be a note-on and the
method will return true. If returnTrueForVelocity0 is false, then
if this is a note-on event with velocity 0, it'll be regarded as
a note-off, and the method will return false
@see isNoteOff, getNoteNumber, getVelocity, noteOn
*/
bool isNoteOn (bool returnTrueForVelocity0 = false) const noexcept;
/** Creates a key-down message (using a floating-point velocity).
@param channel the midi channel, in the range 1 to 16
@param noteNumber the key number, 0 to 127
@param velocity in the range 0 to 1.0
@see isNoteOn
*/
static MidiMessage noteOn (int channel, int noteNumber, float velocity) noexcept;
/** Creates a key-down message (using an integer velocity).
@param channel the midi channel, in the range 1 to 16
@param noteNumber the key number, 0 to 127
@param velocity in the range 0 to 127
@see isNoteOn
*/
static MidiMessage noteOn (int channel, int noteNumber, uint8 velocity) noexcept;
/** Returns true if this message is a 'key-up' event.
If returnTrueForNoteOnVelocity0 is true, then his will also return true
for a note-on event with a velocity of 0.
@see isNoteOn, getNoteNumber, getVelocity, noteOff
*/
bool isNoteOff (bool returnTrueForNoteOnVelocity0 = true) const noexcept;
/** Creates a key-up message.
@param channel the midi channel, in the range 1 to 16
@param noteNumber the key number, 0 to 127
@param velocity in the range 0 to 127
@see isNoteOff
*/
static MidiMessage noteOff (int channel, int noteNumber, uint8 velocity = 0) noexcept;
/** Returns true if this message is a 'key-down' or 'key-up' event.
@see isNoteOn, isNoteOff
*/
bool isNoteOnOrOff() const noexcept;
/** Returns the midi note number for note-on and note-off messages.
If the message isn't a note-on or off, the value returned is undefined.
@see isNoteOff, getMidiNoteName, getMidiNoteInHertz, setNoteNumber
*/
int getNoteNumber() const noexcept;
/** Changes the midi note number of a note-on or note-off message.
If the message isn't a note on or off, this will do nothing.
*/
void setNoteNumber (int newNoteNumber) noexcept;
//==============================================================================
/** Returns the velocity of a note-on or note-off message.
The value returned will be in the range 0 to 127.
If the message isn't a note-on or off event, it will return 0.
@see getFloatVelocity
*/
uint8 getVelocity() const noexcept;
/** Returns the velocity of a note-on or note-off message.
The value returned will be in the range 0 to 1.0
If the message isn't a note-on or off event, it will return 0.
@see getVelocity, setVelocity
*/
float getFloatVelocity() const noexcept;
/** Changes the velocity of a note-on or note-off message.
If the message isn't a note on or off, this will do nothing.
@param newVelocity the new velocity, in the range 0 to 1.0
@see getFloatVelocity, multiplyVelocity
*/
void setVelocity (float newVelocity) noexcept;
/** Multiplies the velocity of a note-on or note-off message by a given amount.
If the message isn't a note on or off, this will do nothing.
@param scaleFactor the value by which to multiply the velocity
@see setVelocity
*/
void multiplyVelocity (float scaleFactor) noexcept;
//==============================================================================
/** Returns true if this message is a 'sustain pedal down' controller message. */
bool isSustainPedalOn() const noexcept;
/** Returns true if this message is a 'sustain pedal up' controller message. */
bool isSustainPedalOff() const noexcept;
/** Returns true if this message is a 'sostenuto pedal down' controller message. */
bool isSostenutoPedalOn() const noexcept;
/** Returns true if this message is a 'sostenuto pedal up' controller message. */
bool isSostenutoPedalOff() const noexcept;
/** Returns true if this message is a 'soft pedal down' controller message. */
bool isSoftPedalOn() const noexcept;
/** Returns true if this message is a 'soft pedal up' controller message. */
bool isSoftPedalOff() const noexcept;
//==============================================================================
/** Returns true if the message is a program (patch) change message.
@see getProgramChangeNumber, getGMInstrumentName
*/
bool isProgramChange() const noexcept;
/** Returns the new program number of a program change message.
If the message isn't a program change, the value returned will be
nonsense.
@see isProgramChange, getGMInstrumentName
*/
int getProgramChangeNumber() const noexcept;
/** Creates a program-change message.
@param channel the midi channel, in the range 1 to 16
@param programNumber the midi program number, 0 to 127
@see isProgramChange, getGMInstrumentName
*/
static MidiMessage programChange (int channel, int programNumber) noexcept;
//==============================================================================
/** Returns true if the message is a pitch-wheel move.
@see getPitchWheelValue, pitchWheel
*/
bool isPitchWheel() const noexcept;
/** Returns the pitch wheel position from a pitch-wheel move message.
The value returned is a 14-bit number from 0 to 0x3fff, indicating the wheel position.
If called for messages which aren't pitch wheel events, the number returned will be
nonsense.
@see isPitchWheel
*/
int getPitchWheelValue() const noexcept;
/** Creates a pitch-wheel move message.
@param channel the midi channel, in the range 1 to 16
@param position the wheel position, in the range 0 to 16383
@see isPitchWheel
*/
static MidiMessage pitchWheel (int channel, int position) noexcept;
//==============================================================================
/** Returns true if the message is an aftertouch event.
For aftertouch events, use the getNoteNumber() method to find out the key
that it applies to, and getAftertouchValue() to find out the amount. Use
getChannel() to find out the channel.
@see getAftertouchValue, getNoteNumber
*/
bool isAftertouch() const noexcept;
/** Returns the amount of aftertouch from an aftertouch messages.
The value returned is in the range 0 to 127, and will be nonsense for messages
other than aftertouch messages.
@see isAftertouch
*/
int getAfterTouchValue() const noexcept;
/** Creates an aftertouch message.
@param channel the midi channel, in the range 1 to 16
@param noteNumber the key number, 0 to 127
@param aftertouchAmount the amount of aftertouch, 0 to 127
@see isAftertouch
*/
static MidiMessage aftertouchChange (int channel,
int noteNumber,
int aftertouchAmount) noexcept;
/** Returns true if the message is a channel-pressure change event.
This is like aftertouch, but common to the whole channel rather than a specific
note. Use getChannelPressureValue() to find out the pressure, and getChannel()
to find out the channel.
@see channelPressureChange
*/
bool isChannelPressure() const noexcept;
/** Returns the pressure from a channel pressure change message.
@returns the pressure, in the range 0 to 127
@see isChannelPressure, channelPressureChange
*/
int getChannelPressureValue() const noexcept;
/** Creates a channel-pressure change event.
@param channel the midi channel: 1 to 16
@param pressure the pressure, 0 to 127
@see isChannelPressure
*/
static MidiMessage channelPressureChange (int channel, int pressure) noexcept;
//==============================================================================
/** Returns true if this is a midi controller message.
@see getControllerNumber, getControllerValue, controllerEvent
*/
bool isController() const noexcept;
/** Returns the controller number of a controller message.
The name of the controller can be looked up using the getControllerName() method.
Note that the value returned is invalid for messages that aren't controller changes.
@see isController, getControllerName, getControllerValue
*/
int getControllerNumber() const noexcept;
/** Returns the controller value from a controller message.
A value 0 to 127 is returned to indicate the new controller position.
Note that the value returned is invalid for messages that aren't controller changes.
@see isController, getControllerNumber
*/
int getControllerValue() const noexcept;
/** Returns true if this message is a controller message and if it has the specified
controller type.
*/
bool isControllerOfType (int controllerType) const noexcept;
/** Creates a controller message.
@param channel the midi channel, in the range 1 to 16
@param controllerType the type of controller
@param value the controller value
@see isController
*/
static MidiMessage controllerEvent (int channel,
int controllerType,
int value) noexcept;
/** Checks whether this message is an all-notes-off message.
@see allNotesOff
*/
bool isAllNotesOff() const noexcept;
/** Checks whether this message is an all-sound-off message.
@see allSoundOff
*/
bool isAllSoundOff() const noexcept;
/** Creates an all-notes-off message.
@param channel the midi channel, in the range 1 to 16
@see isAllNotesOff
*/
static MidiMessage allNotesOff (int channel) noexcept;
/** Creates an all-sound-off message.
@param channel the midi channel, in the range 1 to 16
@see isAllSoundOff
*/
static MidiMessage allSoundOff (int channel) noexcept;
/** Creates an all-controllers-off message.
@param channel the midi channel, in the range 1 to 16
*/
static MidiMessage allControllersOff (int channel) noexcept;
//==============================================================================
/** Returns true if this event is a meta-event.
Meta-events are things like tempo changes, track names, etc.
@see getMetaEventType, isTrackMetaEvent, isEndOfTrackMetaEvent,
isTextMetaEvent, isTrackNameEvent, isTempoMetaEvent, isTimeSignatureMetaEvent,
isKeySignatureMetaEvent, isMidiChannelMetaEvent
*/
bool isMetaEvent() const noexcept;
/** Returns a meta-event's type number.
If the message isn't a meta-event, this will return -1.
@see isMetaEvent, isTrackMetaEvent, isEndOfTrackMetaEvent,
isTextMetaEvent, isTrackNameEvent, isTempoMetaEvent, isTimeSignatureMetaEvent,
isKeySignatureMetaEvent, isMidiChannelMetaEvent
*/
int getMetaEventType() const noexcept;
/** Returns a pointer to the data in a meta-event.
@see isMetaEvent, getMetaEventLength
*/
const uint8* getMetaEventData() const noexcept;
/** Returns the length of the data for a meta-event.
@see isMetaEvent, getMetaEventData
*/
int getMetaEventLength() const noexcept;
//==============================================================================
/** Returns true if this is a 'track' meta-event. */
bool isTrackMetaEvent() const noexcept;
/** Returns true if this is an 'end-of-track' meta-event. */
bool isEndOfTrackMetaEvent() const noexcept;
/** Creates an end-of-track meta-event.
@see isEndOfTrackMetaEvent
*/
static MidiMessage endOfTrack() noexcept;
/** Returns true if this is an 'track name' meta-event.
You can use the getTextFromTextMetaEvent() method to get the track's name.
*/
bool isTrackNameEvent() const noexcept;
/** Returns true if this is a 'text' meta-event.
@see getTextFromTextMetaEvent
*/
bool isTextMetaEvent() const noexcept;
/** Returns the text from a text meta-event.
@see isTextMetaEvent
*/
String getTextFromTextMetaEvent() const;
//==============================================================================
/** Returns true if this is a 'tempo' meta-event.
@see getTempoMetaEventTickLength, getTempoSecondsPerQuarterNote
*/
bool isTempoMetaEvent() const noexcept;
/** Returns the tick length from a tempo meta-event.
@param timeFormat the 16-bit time format value from the midi file's header.
@returns the tick length (in seconds).
@see isTempoMetaEvent
*/
double getTempoMetaEventTickLength (short timeFormat) const noexcept;
/** Calculates the seconds-per-quarter-note from a tempo meta-event.
@see isTempoMetaEvent, getTempoMetaEventTickLength
*/
double getTempoSecondsPerQuarterNote() const noexcept;
/** Creates a tempo meta-event.
@see isTempoMetaEvent
*/
static MidiMessage tempoMetaEvent (int microsecondsPerQuarterNote) noexcept;
//==============================================================================
/** Returns true if this is a 'time-signature' meta-event.
@see getTimeSignatureInfo
*/
bool isTimeSignatureMetaEvent() const noexcept;
/** Returns the time-signature values from a time-signature meta-event.
@see isTimeSignatureMetaEvent
*/
void getTimeSignatureInfo (int& numerator, int& denominator) const noexcept;
/** Creates a time-signature meta-event.
@see isTimeSignatureMetaEvent
*/
static MidiMessage timeSignatureMetaEvent (int numerator, int denominator);
//==============================================================================
/** Returns true if this is a 'key-signature' meta-event.
@see getKeySignatureNumberOfSharpsOrFlats
*/
bool isKeySignatureMetaEvent() const noexcept;
/** Returns the key from a key-signature meta-event.
@see isKeySignatureMetaEvent
*/
int getKeySignatureNumberOfSharpsOrFlats() const noexcept;
//==============================================================================
/** Returns true if this is a 'channel' meta-event.
A channel meta-event specifies the midi channel that should be used
for subsequent meta-events.
@see getMidiChannelMetaEventChannel
*/
bool isMidiChannelMetaEvent() const noexcept;
/** Returns the channel number from a channel meta-event.
@returns the channel, in the range 1 to 16.
@see isMidiChannelMetaEvent
*/
int getMidiChannelMetaEventChannel() const noexcept;
/** Creates a midi channel meta-event.
@param channel the midi channel, in the range 1 to 16
@see isMidiChannelMetaEvent
*/
static MidiMessage midiChannelMetaEvent (int channel) noexcept;
//==============================================================================
/** Returns true if this is an active-sense message. */
bool isActiveSense() const noexcept;
//==============================================================================
/** Returns true if this is a midi start event.
@see midiStart
*/
bool isMidiStart() const noexcept;
/** Creates a midi start event. */
static MidiMessage midiStart() noexcept;
/** Returns true if this is a midi continue event.
@see midiContinue
*/
bool isMidiContinue() const noexcept;
/** Creates a midi continue event. */
static MidiMessage midiContinue() noexcept;
/** Returns true if this is a midi stop event.
@see midiStop
*/
bool isMidiStop() const noexcept;
/** Creates a midi stop event. */
static MidiMessage midiStop() noexcept;
/** Returns true if this is a midi clock event.
@see midiClock, songPositionPointer
*/
bool isMidiClock() const noexcept;
/** Creates a midi clock event. */
static MidiMessage midiClock() noexcept;
/** Returns true if this is a song-position-pointer message.
@see getSongPositionPointerMidiBeat, songPositionPointer
*/
bool isSongPositionPointer() const noexcept;
/** Returns the midi beat-number of a song-position-pointer message.
@see isSongPositionPointer, songPositionPointer
*/
int getSongPositionPointerMidiBeat() const noexcept;
/** Creates a song-position-pointer message.
The position is a number of midi beats from the start of the song, where 1 midi
beat is 6 midi clocks, and there are 24 midi clocks in a quarter-note. So there
are 4 midi beats in a quarter-note.
@see isSongPositionPointer, getSongPositionPointerMidiBeat
*/
static MidiMessage songPositionPointer (int positionInMidiBeats) noexcept;
//==============================================================================
/** Returns true if this is a quarter-frame midi timecode message.
@see quarterFrame, getQuarterFrameSequenceNumber, getQuarterFrameValue
*/
bool isQuarterFrame() const noexcept;
/** Returns the sequence number of a quarter-frame midi timecode message.
This will be a value between 0 and 7.
@see isQuarterFrame, getQuarterFrameValue, quarterFrame
*/
int getQuarterFrameSequenceNumber() const noexcept;
/** Returns the value from a quarter-frame message.
This will be the lower nybble of the message's data-byte, a value
between 0 and 15
*/
int getQuarterFrameValue() const noexcept;
/** Creates a quarter-frame MTC message.
@param sequenceNumber a value 0 to 7 for the upper nybble of the message's data byte
@param value a value 0 to 15 for the lower nybble of the message's data byte
*/
static MidiMessage quarterFrame (int sequenceNumber, int value) noexcept;
/** SMPTE timecode types.
Used by the getFullFrameParameters() and fullFrame() methods.
*/
enum SmpteTimecodeType
{
fps24 = 0,
fps25 = 1,
fps30drop = 2,
fps30 = 3
};
/** Returns true if this is a full-frame midi timecode message.
*/
bool isFullFrame() const noexcept;
/** Extracts the timecode information from a full-frame midi timecode message.
You should only call this on messages where you've used isFullFrame() to
check that they're the right kind.
*/
void getFullFrameParameters (int& hours,
int& minutes,
int& seconds,
int& frames,
SmpteTimecodeType& timecodeType) const noexcept;
/** Creates a full-frame MTC message.
*/
static MidiMessage fullFrame (int hours,
int minutes,
int seconds,
int frames,
SmpteTimecodeType timecodeType);
//==============================================================================
/** Types of MMC command.
@see isMidiMachineControlMessage, getMidiMachineControlCommand, midiMachineControlCommand
*/
enum MidiMachineControlCommand
{
mmc_stop = 1,
mmc_play = 2,
mmc_deferredplay = 3,
mmc_fastforward = 4,
mmc_rewind = 5,
mmc_recordStart = 6,
mmc_recordStop = 7,
mmc_pause = 9
};
/** Checks whether this is an MMC message.
If it is, you can use the getMidiMachineControlCommand() to find out its type.
*/
bool isMidiMachineControlMessage() const noexcept;
/** For an MMC message, this returns its type.
Make sure it's actually an MMC message with isMidiMachineControlMessage() before
calling this method.
*/
MidiMachineControlCommand getMidiMachineControlCommand() const noexcept;
/** Creates an MMC message.
*/
static MidiMessage midiMachineControlCommand (MidiMachineControlCommand command);
/** Checks whether this is an MMC "goto" message.
If it is, the parameters passed-in are set to the time that the message contains.
@see midiMachineControlGoto
*/
bool isMidiMachineControlGoto (int& hours,
int& minutes,
int& seconds,
int& frames) const noexcept;
/** Creates an MMC "goto" message.
This messages tells the device to go to a specific frame.
@see isMidiMachineControlGoto
*/
static MidiMessage midiMachineControlGoto (int hours,
int minutes,
int seconds,
int frames);
//==============================================================================
/** Creates a master-volume change message.
@param volume the volume, 0 to 1.0
*/
static MidiMessage masterVolume (float volume);
//==============================================================================
/** Creates a system-exclusive message.
The data passed in is wrapped with header and tail bytes of 0xf0 and 0xf7.
*/
static MidiMessage createSysExMessage (const uint8* sysexData,
int dataSize);
//==============================================================================
/** Reads a midi variable-length integer.
@param data the data to read the number from
@param numBytesUsed on return, this will be set to the number of bytes that were read
*/
static int readVariableLengthVal (const uint8* data,
int& numBytesUsed) noexcept;
/** Based on the first byte of a short midi message, this uses a lookup table
to return the message length (either 1, 2, or 3 bytes).
The value passed in must be 0x80 or higher.
*/
static int getMessageLengthFromFirstByte (const uint8 firstByte) noexcept;
//==============================================================================
/** Returns the name of a midi note number.
E.g "C", "D#", etc.
@param noteNumber the midi note number, 0 to 127
@param useSharps if true, sharpened notes are used, e.g. "C#", otherwise
they'll be flattened, e.g. "Db"
@param includeOctaveNumber if true, the octave number will be appended to the string,
e.g. "C#4"
@param octaveNumForMiddleC if an octave number is being appended, this indicates the
number that will be used for middle C's octave
@see getMidiNoteInHertz
*/
static String getMidiNoteName (int noteNumber,
bool useSharps,
bool includeOctaveNumber,
int octaveNumForMiddleC);
/** Returns the frequency of a midi note number.
The frequencyOfA parameter is an optional frequency for 'A', normally 440-444Hz for concert pitch.
@see getMidiNoteName
*/
static double getMidiNoteInHertz (int noteNumber, const double frequencyOfA = 440.0) noexcept;
/** Returns the standard name of a GM instrument.
@param midiInstrumentNumber the program number 0 to 127
@see getProgramChangeNumber
*/
static String getGMInstrumentName (int midiInstrumentNumber);
/** Returns the name of a bank of GM instruments.
@param midiBankNumber the bank, 0 to 15
*/
static String getGMInstrumentBankName (int midiBankNumber);
/** Returns the standard name of a channel 10 percussion sound.
@param midiNoteNumber the key number, 35 to 81
*/
static String getRhythmInstrumentName (int midiNoteNumber);
/** Returns the name of a controller type number.
@see getControllerNumber
*/
static String getControllerName (int controllerNumber);
private:
//==============================================================================
double timeStamp;
uint8* data;
int size;
#ifndef DOXYGEN
union
{
uint8 asBytes[4];
uint32 asInt32;
} preallocatedData;
#endif
void freeData() noexcept;
void setToUseInternalData() noexcept;
bool usesAllocatedData() const noexcept;
};
#endif // __JUCE_MIDIMESSAGE_JUCEHEADER__

+ 335
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp View File

@@ -0,0 +1,335 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
MidiMessageSequence::MidiMessageSequence()
{
}
MidiMessageSequence::MidiMessageSequence (const MidiMessageSequence& other)
{
list.ensureStorageAllocated (other.list.size());
for (int i = 0; i < other.list.size(); ++i)
list.add (new MidiEventHolder (other.list.getUnchecked(i)->message));
}
MidiMessageSequence& MidiMessageSequence::operator= (const MidiMessageSequence& other)
{
MidiMessageSequence otherCopy (other);
swapWith (otherCopy);
return *this;
}
void MidiMessageSequence::swapWith (MidiMessageSequence& other) noexcept
{
list.swapWithArray (other.list);
}
MidiMessageSequence::~MidiMessageSequence()
{
}
void MidiMessageSequence::clear()
{
list.clear();
}
int MidiMessageSequence::getNumEvents() const
{
return list.size();
}
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::getEventPointer (const int index) const
{
return list [index];
}
double MidiMessageSequence::getTimeOfMatchingKeyUp (const int index) const
{
if (const MidiEventHolder* const meh = list [index])
if (meh->noteOffObject != nullptr)
return meh->noteOffObject->message.getTimeStamp();
return 0.0;
}
int MidiMessageSequence::getIndexOfMatchingKeyUp (const int index) const
{
if (const MidiEventHolder* const meh = list [index])
return list.indexOf (meh->noteOffObject);
return -1;
}
int MidiMessageSequence::getIndexOf (MidiEventHolder* const event) const
{
return list.indexOf (event);
}
int MidiMessageSequence::getNextIndexAtTime (const double timeStamp) const
{
const int numEvents = list.size();
int i;
for (i = 0; i < numEvents; ++i)
if (list.getUnchecked(i)->message.getTimeStamp() >= timeStamp)
break;
return i;
}
//==============================================================================
double MidiMessageSequence::getStartTime() const
{
return getEventTime (0);
}
double MidiMessageSequence::getEndTime() const
{
return getEventTime (list.size() - 1);
}
double MidiMessageSequence::getEventTime (const int index) const
{
if (const MidiEventHolder* const meh = list [index])
return meh->message.getTimeStamp();
return 0.0;
}
//==============================================================================
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::addEvent (const MidiMessage& newMessage,
double timeAdjustment)
{
MidiEventHolder* const newOne = new MidiEventHolder (newMessage);
timeAdjustment += newMessage.getTimeStamp();
newOne->message.setTimeStamp (timeAdjustment);
int i;
for (i = list.size(); --i >= 0;)
if (list.getUnchecked(i)->message.getTimeStamp() <= timeAdjustment)
break;
list.insert (i + 1, newOne);
return newOne;
}
void MidiMessageSequence::deleteEvent (const int index,
const bool deleteMatchingNoteUp)
{
if (isPositiveAndBelow (index, list.size()))
{
if (deleteMatchingNoteUp)
deleteEvent (getIndexOfMatchingKeyUp (index), false);
list.remove (index);
}
}
struct MidiMessageSequenceSorter
{
static int compareElements (const MidiMessageSequence::MidiEventHolder* const first,
const MidiMessageSequence::MidiEventHolder* const second) noexcept
{
const double diff = first->message.getTimeStamp() - second->message.getTimeStamp();
return (diff > 0) - (diff < 0);
}
};
void MidiMessageSequence::addSequence (const MidiMessageSequence& other,
double timeAdjustment,
double firstAllowableTime,
double endOfAllowableDestTimes)
{
firstAllowableTime -= timeAdjustment;
endOfAllowableDestTimes -= timeAdjustment;
for (int i = 0; i < other.list.size(); ++i)
{
const MidiMessage& m = other.list.getUnchecked(i)->message;
const double t = m.getTimeStamp();
if (t >= firstAllowableTime && t < endOfAllowableDestTimes)
{
MidiEventHolder* const newOne = new MidiEventHolder (m);
newOne->message.setTimeStamp (timeAdjustment + t);
list.add (newOne);
}
}
sort();
}
//==============================================================================
void MidiMessageSequence::sort()
{
MidiMessageSequenceSorter sorter;
list.sort (sorter, true);
}
void MidiMessageSequence::updateMatchedPairs()
{
for (int i = 0; i < list.size(); ++i)
{
MidiEventHolder* const meh = list.getUnchecked(i);
const MidiMessage& m1 = meh->message;
if (m1.isNoteOn())
{
meh->noteOffObject = nullptr;
const int note = m1.getNoteNumber();
const int chan = m1.getChannel();
const int len = list.size();
for (int j = i + 1; j < len; ++j)
{
const MidiMessage& m = list.getUnchecked(j)->message;
if (m.getNoteNumber() == note && m.getChannel() == chan)
{
if (m.isNoteOff())
{
meh->noteOffObject = list[j];
break;
}
else if (m.isNoteOn())
{
MidiEventHolder* const newEvent = new MidiEventHolder (MidiMessage::noteOff (chan, note));
list.insert (j, newEvent);
newEvent->message.setTimeStamp (m.getTimeStamp());
meh->noteOffObject = newEvent;
break;
}
}
}
}
}
}
void MidiMessageSequence::addTimeToMessages (const double delta)
{
for (int i = list.size(); --i >= 0;)
{
MidiMessage& mm = list.getUnchecked(i)->message;
mm.setTimeStamp (mm.getTimeStamp() + delta);
}
}
//==============================================================================
void MidiMessageSequence::extractMidiChannelMessages (const int channelNumberToExtract,
MidiMessageSequence& destSequence,
const bool alsoIncludeMetaEvents) const
{
for (int i = 0; i < list.size(); ++i)
{
const MidiMessage& mm = list.getUnchecked(i)->message;
if (mm.isForChannel (channelNumberToExtract) || (alsoIncludeMetaEvents && mm.isMetaEvent()))
destSequence.addEvent (mm);
}
}
void MidiMessageSequence::extractSysExMessages (MidiMessageSequence& destSequence) const
{
for (int i = 0; i < list.size(); ++i)
{
const MidiMessage& mm = list.getUnchecked(i)->message;
if (mm.isSysEx())
destSequence.addEvent (mm);
}
}
void MidiMessageSequence::deleteMidiChannelMessages (const int channelNumberToRemove)
{
for (int i = list.size(); --i >= 0;)
if (list.getUnchecked(i)->message.isForChannel (channelNumberToRemove))
list.remove(i);
}
void MidiMessageSequence::deleteSysExMessages()
{
for (int i = list.size(); --i >= 0;)
if (list.getUnchecked(i)->message.isSysEx())
list.remove(i);
}
//==============================================================================
void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumber,
const double time,
OwnedArray<MidiMessage>& dest)
{
bool doneProg = false;
bool donePitchWheel = false;
Array <int> doneControllers;
doneControllers.ensureStorageAllocated (32);
for (int i = list.size(); --i >= 0;)
{
const MidiMessage& mm = list.getUnchecked(i)->message;
if (mm.isForChannel (channelNumber) && mm.getTimeStamp() <= time)
{
if (mm.isProgramChange())
{
if (! doneProg)
{
dest.add (new MidiMessage (mm, 0.0));
doneProg = true;
}
}
else if (mm.isController())
{
if (! doneControllers.contains (mm.getControllerNumber()))
{
dest.add (new MidiMessage (mm, 0.0));
doneControllers.add (mm.getControllerNumber());
}
}
else if (mm.isPitchWheel())
{
if (! donePitchWheel)
{
dest.add (new MidiMessage (mm, 0.0));
donePitchWheel = true;
}
}
}
}
}
//==============================================================================
MidiMessageSequence::MidiEventHolder::MidiEventHolder (const MidiMessage& mm)
: message (mm),
noteOffObject (nullptr)
{
}
MidiMessageSequence::MidiEventHolder::~MidiEventHolder()
{
}

+ 281
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h View File

@@ -0,0 +1,281 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__
#define __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__
#include "juce_MidiMessage.h"
//==============================================================================
/**
A sequence of timestamped midi messages.
This allows the sequence to be manipulated, and also to be read from and
written to a standard midi file.
@see MidiMessage, MidiFile
*/
class JUCE_API MidiMessageSequence
{
public:
//==============================================================================
/** Creates an empty midi sequence object. */
MidiMessageSequence();
/** Creates a copy of another sequence. */
MidiMessageSequence (const MidiMessageSequence& other);
/** Replaces this sequence with another one. */
MidiMessageSequence& operator= (const MidiMessageSequence& other);
/** Destructor. */
~MidiMessageSequence();
//==============================================================================
/** Structure used to hold midi events in the sequence.
These structures act as 'handles' on the events as they are moved about in
the list, and make it quick to find the matching note-offs for note-on events.
@see MidiMessageSequence::getEventPointer
*/
class MidiEventHolder
{
public:
//==============================================================================
/** Destructor. */
~MidiEventHolder();
/** The message itself, whose timestamp is used to specify the event's time.
*/
MidiMessage message;
/** The matching note-off event (if this is a note-on event).
If this isn't a note-on, this pointer will be null.
Use the MidiMessageSequence::updateMatchedPairs() method to keep these
note-offs up-to-date after events have been moved around in the sequence
or deleted.
*/
MidiEventHolder* noteOffObject;
private:
//==============================================================================
friend class MidiMessageSequence;
MidiEventHolder (const MidiMessage& message);
JUCE_LEAK_DETECTOR (MidiEventHolder)
};
//==============================================================================
/** Clears the sequence. */
void clear();
/** Returns the number of events in the sequence. */
int getNumEvents() const;
/** Returns a pointer to one of the events. */
MidiEventHolder* getEventPointer (int index) const;
/** Returns the time of the note-up that matches the note-on at this index.
If the event at this index isn't a note-on, it'll just return 0.
@see MidiMessageSequence::MidiEventHolder::noteOffObject
*/
double getTimeOfMatchingKeyUp (int index) const;
/** Returns the index of the note-up that matches the note-on at this index.
If the event at this index isn't a note-on, it'll just return -1.
@see MidiMessageSequence::MidiEventHolder::noteOffObject
*/
int getIndexOfMatchingKeyUp (int index) const;
/** Returns the index of an event. */
int getIndexOf (MidiEventHolder* event) const;
/** Returns the index of the first event on or after the given timestamp.
If the time is beyond the end of the sequence, this will return the
number of events.
*/
int getNextIndexAtTime (double timeStamp) const;
//==============================================================================
/** Returns the timestamp of the first event in the sequence.
@see getEndTime
*/
double getStartTime() const;
/** Returns the timestamp of the last event in the sequence.
@see getStartTime
*/
double getEndTime() const;
/** Returns the timestamp of the event at a given index.
If the index is out-of-range, this will return 0.0
*/
double getEventTime (int index) const;
//==============================================================================
/** Inserts a midi message into the sequence.
The index at which the new message gets inserted will depend on its timestamp,
because the sequence is kept sorted.
Remember to call updateMatchedPairs() after adding note-on events.
@param newMessage the new message to add (an internal copy will be made)
@param timeAdjustment an optional value to add to the timestamp of the message
that will be inserted
@see updateMatchedPairs
*/
MidiEventHolder* addEvent (const MidiMessage& newMessage,
double timeAdjustment = 0);
/** Deletes one of the events in the sequence.
Remember to call updateMatchedPairs() after removing events.
@param index the index of the event to delete
@param deleteMatchingNoteUp whether to also remove the matching note-off
if the event you're removing is a note-on
*/
void deleteEvent (int index, bool deleteMatchingNoteUp);
/** Merges another sequence into this one.
Remember to call updateMatchedPairs() after using this method.
@param other the sequence to add from
@param timeAdjustmentDelta an amount to add to the timestamps of the midi events
as they are read from the other sequence
@param firstAllowableDestTime events will not be added if their time is earlier
than this time. (This is after their time has been adjusted
by the timeAdjustmentDelta)
@param endOfAllowableDestTimes events will not be added if their time is equal to
or greater than this time. (This is after their time has
been adjusted by the timeAdjustmentDelta)
*/
void addSequence (const MidiMessageSequence& other,
double timeAdjustmentDelta,
double firstAllowableDestTime,
double endOfAllowableDestTimes);
//==============================================================================
/** Makes sure all the note-on and note-off pairs are up-to-date.
Call this after moving messages about or deleting/adding messages, and it
will scan the list and make sure all the note-offs in the MidiEventHolder
structures are pointing at the correct ones.
*/
void updateMatchedPairs();
/** Forces a sort of the sequence.
You may need to call this if you've manually modified the timestamps of some
events such that the overall order now needs updating.
*/
void sort();
//==============================================================================
/** Copies all the messages for a particular midi channel to another sequence.
@param channelNumberToExtract the midi channel to look for, in the range 1 to 16
@param destSequence the sequence that the chosen events should be copied to
@param alsoIncludeMetaEvents if true, any meta-events (which don't apply to a specific
channel) will also be copied across.
@see extractSysExMessages
*/
void extractMidiChannelMessages (int channelNumberToExtract,
MidiMessageSequence& destSequence,
bool alsoIncludeMetaEvents) const;
/** Copies all midi sys-ex messages to another sequence.
@param destSequence this is the sequence to which any sys-exes in this sequence
will be added
@see extractMidiChannelMessages
*/
void extractSysExMessages (MidiMessageSequence& destSequence) const;
/** Removes any messages in this sequence that have a specific midi channel.
@param channelNumberToRemove the midi channel to look for, in the range 1 to 16
*/
void deleteMidiChannelMessages (int channelNumberToRemove);
/** Removes any sys-ex messages from this sequence.
*/
void deleteSysExMessages();
/** Adds an offset to the timestamps of all events in the sequence.
@param deltaTime the amount to add to each timestamp.
*/
void addTimeToMessages (double deltaTime);
//==============================================================================
/** Scans through the sequence to determine the state of any midi controllers at
a given time.
This will create a sequence of midi controller changes that can be
used to set all midi controllers to the state they would be in at the
specified time within this sequence.
As well as controllers, it will also recreate the midi program number
and pitch bend position.
@param channelNumber the midi channel to look for, in the range 1 to 16. Controllers
for other channels will be ignored.
@param time the time at which you want to find out the state - there are
no explicit units for this time measurement, it's the same units
as used for the timestamps of the messages
@param resultMessages an array to which midi controller-change messages will be added. This
will be the minimum number of controller changes to recreate the
state at the required time.
*/
void createControllerUpdatesForTime (int channelNumber, double time,
OwnedArray<MidiMessage>& resultMessages);
//==============================================================================
/** Swaps this sequence with another one. */
void swapWith (MidiMessageSequence& other) noexcept;
private:
//==============================================================================
friend class MidiFile;
OwnedArray <MidiEventHolder> list;
JUCE_LEAK_DETECTOR (MidiMessageSequence)
};
#endif // __JUCE_MIDIMESSAGESEQUENCE_JUCEHEADER__

+ 184
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_AudioSource.h View File

@@ -0,0 +1,184 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOSOURCE_JUCEHEADER__
#define __JUCE_AUDIOSOURCE_JUCEHEADER__
#include "../buffers/juce_AudioSampleBuffer.h"
//==============================================================================
/**
Used by AudioSource::getNextAudioBlock().
*/
struct JUCE_API AudioSourceChannelInfo
{
/** Creates an uninitialised AudioSourceChannelInfo. */
AudioSourceChannelInfo() noexcept
{
}
/** Creates an AudioSourceChannelInfo. */
AudioSourceChannelInfo (AudioSampleBuffer* bufferToUse,
int startSampleOffset, int numSamplesToUse) noexcept
: buffer (bufferToUse),
startSample (startSampleOffset),
numSamples (numSamplesToUse)
{
}
/** Creates an AudioSourceChannelInfo that uses the whole of a buffer.
Note that the buffer provided must not be deleted while the
AudioSourceChannelInfo is still using it.
*/
explicit AudioSourceChannelInfo (AudioSampleBuffer& bufferToUse) noexcept
: buffer (&bufferToUse),
startSample (0),
numSamples (bufferToUse.getNumSamples())
{
}
/** The destination buffer to fill with audio data.
When the AudioSource::getNextAudioBlock() method is called, the active section
of this buffer should be filled with whatever output the source produces.
Only the samples specified by the startSample and numSamples members of this structure
should be affected by the call.
The contents of the buffer when it is passed to the the AudioSource::getNextAudioBlock()
method can be treated as the input if the source is performing some kind of filter operation,
but should be cleared if this is not the case - the clearActiveBufferRegion() is
a handy way of doing this.
The number of channels in the buffer could be anything, so the AudioSource
must cope with this in whatever way is appropriate for its function.
*/
AudioSampleBuffer* buffer;
/** The first sample in the buffer from which the callback is expected
to write data. */
int startSample;
/** The number of samples in the buffer which the callback is expected to
fill with data. */
int numSamples;
/** Convenient method to clear the buffer if the source is not producing any data. */
void clearActiveBufferRegion() const
{
if (buffer != nullptr)
buffer->clear (startSample, numSamples);
}
};
//==============================================================================
/**
Base class for objects that can produce a continuous stream of audio.
An AudioSource has two states: 'prepared' and 'unprepared'.
When a source needs to be played, it is first put into a 'prepared' state by a call to
prepareToPlay(), and then repeated calls will be made to its getNextAudioBlock() method to
process the audio data.
Once playback has finished, the releaseResources() method is called to put the stream
back into an 'unprepared' state.
@see AudioFormatReaderSource, ResamplingAudioSource
*/
class JUCE_API AudioSource
{
protected:
//==============================================================================
/** Creates an AudioSource. */
AudioSource() noexcept {}
public:
/** Destructor. */
virtual ~AudioSource() {}
//==============================================================================
/** Tells the source to prepare for playing.
An AudioSource has two states: prepared and unprepared.
The prepareToPlay() method is guaranteed to be called at least once on an 'unpreprared'
source to put it into a 'prepared' state before any calls will be made to getNextAudioBlock().
This callback allows the source to initialise any resources it might need when playing.
Once playback has finished, the releaseResources() method is called to put the stream
back into an 'unprepared' state.
Note that this method could be called more than once in succession without
a matching call to releaseResources(), so make sure your code is robust and
can handle that kind of situation.
@param samplesPerBlockExpected the number of samples that the source
will be expected to supply each time its
getNextAudioBlock() method is called. This
number may vary slightly, because it will be dependent
on audio hardware callbacks, and these aren't
guaranteed to always use a constant block size, so
the source should be able to cope with small variations.
@param sampleRate the sample rate that the output will be used at - this
is needed by sources such as tone generators.
@see releaseResources, getNextAudioBlock
*/
virtual void prepareToPlay (int samplesPerBlockExpected,
double sampleRate) = 0;
/** Allows the source to release anything it no longer needs after playback has stopped.
This will be called when the source is no longer going to have its getNextAudioBlock()
method called, so it should release any spare memory, etc. that it might have
allocated during the prepareToPlay() call.
Note that there's no guarantee that prepareToPlay() will actually have been called before
releaseResources(), and it may be called more than once in succession, so make sure your
code is robust and doesn't make any assumptions about when it will be called.
@see prepareToPlay, getNextAudioBlock
*/
virtual void releaseResources() = 0;
/** Called repeatedly to fetch subsequent blocks of audio data.
After calling the prepareToPlay() method, this callback will be made each
time the audio playback hardware (or whatever other destination the audio
data is going to) needs another block of data.
It will generally be called on a high-priority system thread, or possibly even
an interrupt, so be careful not to do too much work here, as that will cause
audio glitches!
@see AudioSourceChannelInfo, prepareToPlay, releaseResources
*/
virtual void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill) = 0;
};
#endif // __JUCE_AUDIOSOURCE_JUCEHEADER__

+ 262
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp View File

@@ -0,0 +1,262 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
BufferingAudioSource::BufferingAudioSource (PositionableAudioSource* source_,
TimeSliceThread& backgroundThread_,
const bool deleteSourceWhenDeleted,
const int numberOfSamplesToBuffer_,
const int numberOfChannels_)
: source (source_, deleteSourceWhenDeleted),
backgroundThread (backgroundThread_),
numberOfSamplesToBuffer (jmax (1024, numberOfSamplesToBuffer_)),
numberOfChannels (numberOfChannels_),
buffer (numberOfChannels_, 0),
bufferValidStart (0),
bufferValidEnd (0),
nextPlayPos (0),
wasSourceLooping (false),
isPrepared (false)
{
jassert (source_ != nullptr);
jassert (numberOfSamplesToBuffer_ > 1024); // not much point using this class if you're
// not using a larger buffer..
}
BufferingAudioSource::~BufferingAudioSource()
{
releaseResources();
}
//==============================================================================
void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate_)
{
const int bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer);
if (sampleRate_ != sampleRate
|| bufferSizeNeeded != buffer.getNumSamples()
|| ! isPrepared)
{
backgroundThread.removeTimeSliceClient (this);
isPrepared = true;
sampleRate = sampleRate_;
source->prepareToPlay (samplesPerBlockExpected, sampleRate_);
buffer.setSize (numberOfChannels, bufferSizeNeeded);
buffer.clear();
bufferValidStart = 0;
bufferValidEnd = 0;
backgroundThread.addTimeSliceClient (this);
while (bufferValidEnd - bufferValidStart < jmin (((int) sampleRate_) / 4,
buffer.getNumSamples() / 2))
{
backgroundThread.moveToFrontOfQueue (this);
Thread::sleep (5);
}
}
}
void BufferingAudioSource::releaseResources()
{
isPrepared = false;
backgroundThread.removeTimeSliceClient (this);
buffer.setSize (numberOfChannels, 0);
source->releaseResources();
}
void BufferingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
const ScopedLock sl (bufferStartPosLock);
const int validStart = (int) (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos) - nextPlayPos);
const int validEnd = (int) (jlimit (bufferValidStart, bufferValidEnd, nextPlayPos + info.numSamples) - nextPlayPos);
if (validStart == validEnd)
{
// total cache miss
info.clearActiveBufferRegion();
}
else
{
if (validStart > 0)
info.buffer->clear (info.startSample, validStart); // partial cache miss at start
if (validEnd < info.numSamples)
info.buffer->clear (info.startSample + validEnd,
info.numSamples - validEnd); // partial cache miss at end
if (validStart < validEnd)
{
for (int chan = jmin (numberOfChannels, info.buffer->getNumChannels()); --chan >= 0;)
{
jassert (buffer.getNumSamples() > 0);
const int startBufferIndex = (int) ((validStart + nextPlayPos) % buffer.getNumSamples());
const int endBufferIndex = (int) ((validEnd + nextPlayPos) % buffer.getNumSamples());
if (startBufferIndex < endBufferIndex)
{
info.buffer->copyFrom (chan, info.startSample + validStart,
buffer,
chan, startBufferIndex,
validEnd - validStart);
}
else
{
const int initialSize = buffer.getNumSamples() - startBufferIndex;
info.buffer->copyFrom (chan, info.startSample + validStart,
buffer,
chan, startBufferIndex,
initialSize);
info.buffer->copyFrom (chan, info.startSample + validStart + initialSize,
buffer,
chan, 0,
(validEnd - validStart) - initialSize);
}
}
}
nextPlayPos += info.numSamples;
}
}
int64 BufferingAudioSource::getNextReadPosition() const
{
jassert (source->getTotalLength() > 0);
return (source->isLooping() && nextPlayPos > 0)
? nextPlayPos % source->getTotalLength()
: nextPlayPos;
}
void BufferingAudioSource::setNextReadPosition (int64 newPosition)
{
const ScopedLock sl (bufferStartPosLock);
nextPlayPos = newPosition;
backgroundThread.moveToFrontOfQueue (this);
}
bool BufferingAudioSource::readNextBufferChunk()
{
int64 newBVS, newBVE, sectionToReadStart, sectionToReadEnd;
{
const ScopedLock sl (bufferStartPosLock);
if (wasSourceLooping != isLooping())
{
wasSourceLooping = isLooping();
bufferValidStart = 0;
bufferValidEnd = 0;
}
newBVS = jmax ((int64) 0, nextPlayPos);
newBVE = newBVS + buffer.getNumSamples() - 4;
sectionToReadStart = 0;
sectionToReadEnd = 0;
const int maxChunkSize = 2048;
if (newBVS < bufferValidStart || newBVS >= bufferValidEnd)
{
newBVE = jmin (newBVE, newBVS + maxChunkSize);
sectionToReadStart = newBVS;
sectionToReadEnd = newBVE;
bufferValidStart = 0;
bufferValidEnd = 0;
}
else if (std::abs ((int) (newBVS - bufferValidStart)) > 512
|| std::abs ((int) (newBVE - bufferValidEnd)) > 512)
{
newBVE = jmin (newBVE, bufferValidEnd + maxChunkSize);
sectionToReadStart = bufferValidEnd;
sectionToReadEnd = newBVE;
bufferValidStart = newBVS;
bufferValidEnd = jmin (bufferValidEnd, newBVE);
}
}
if (sectionToReadStart != sectionToReadEnd)
{
jassert (buffer.getNumSamples() > 0);
const int bufferIndexStart = (int) (sectionToReadStart % buffer.getNumSamples());
const int bufferIndexEnd = (int) (sectionToReadEnd % buffer.getNumSamples());
if (bufferIndexStart < bufferIndexEnd)
{
readBufferSection (sectionToReadStart,
(int) (sectionToReadEnd - sectionToReadStart),
bufferIndexStart);
}
else
{
const int initialSize = buffer.getNumSamples() - bufferIndexStart;
readBufferSection (sectionToReadStart,
initialSize,
bufferIndexStart);
readBufferSection (sectionToReadStart + initialSize,
(int) (sectionToReadEnd - sectionToReadStart) - initialSize,
0);
}
const ScopedLock sl2 (bufferStartPosLock);
bufferValidStart = newBVS;
bufferValidEnd = newBVE;
return true;
}
else
{
return false;
}
}
void BufferingAudioSource::readBufferSection (const int64 start, const int length, const int bufferOffset)
{
if (source->getNextReadPosition() != start)
source->setNextReadPosition (start);
AudioSourceChannelInfo info (&buffer, bufferOffset, length);
source->getNextAudioBlock (info);
}
int BufferingAudioSource::useTimeSlice()
{
return readNextBufferChunk() ? 1 : 100;
}

+ 114
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.h View File

@@ -0,0 +1,114 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__
#define __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__
#include "juce_PositionableAudioSource.h"
//==============================================================================
/**
An AudioSource which takes another source as input, and buffers it using a thread.
Create this as a wrapper around another thread, and it will read-ahead with
a background thread to smooth out playback. You can either create one of these
directly, or use it indirectly using an AudioTransportSource.
@see PositionableAudioSource, AudioTransportSource
*/
class JUCE_API BufferingAudioSource : public PositionableAudioSource,
private TimeSliceClient
{
public:
//==============================================================================
/** Creates a BufferingAudioSource.
@param source the input source to read from
@param backgroundThread a background thread that will be used for the
background read-ahead. This object must not be deleted
until after any BufferedAudioSources that are using it
have been deleted!
@param deleteSourceWhenDeleted if true, then the input source object will
be deleted when this object is deleted
@param numberOfSamplesToBuffer the size of buffer to use for reading ahead
@param numberOfChannels the number of channels that will be played
*/
BufferingAudioSource (PositionableAudioSource* source,
TimeSliceThread& backgroundThread,
bool deleteSourceWhenDeleted,
int numberOfSamplesToBuffer,
int numberOfChannels = 2);
/** Destructor.
The input source may be deleted depending on whether the deleteSourceWhenDeleted
flag was set in the constructor.
*/
~BufferingAudioSource();
//==============================================================================
/** Implementation of the AudioSource method. */
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
/** Implementation of the AudioSource method. */
void releaseResources();
/** Implementation of the AudioSource method. */
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);
//==============================================================================
/** Implements the PositionableAudioSource method. */
void setNextReadPosition (int64 newPosition);
/** Implements the PositionableAudioSource method. */
int64 getNextReadPosition() const;
/** Implements the PositionableAudioSource method. */
int64 getTotalLength() const { return source->getTotalLength(); }
/** Implements the PositionableAudioSource method. */
bool isLooping() const { return source->isLooping(); }
private:
//==============================================================================
OptionalScopedPointer<PositionableAudioSource> source;
TimeSliceThread& backgroundThread;
int numberOfSamplesToBuffer, numberOfChannels;
AudioSampleBuffer buffer;
CriticalSection bufferStartPosLock;
int64 volatile bufferValidStart, bufferValidEnd, nextPlayPos;
double volatile sampleRate;
bool wasSourceLooping, isPrepared;
bool readNextBufferChunk();
void readBufferSection (int64 start, int length, int bufferOffset);
int useTimeSlice();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BufferingAudioSource)
};
#endif // __JUCE_BUFFERINGAUDIOSOURCE_JUCEHEADER__

+ 186
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.cpp View File

@@ -0,0 +1,186 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
ChannelRemappingAudioSource::ChannelRemappingAudioSource (AudioSource* const source_,
const bool deleteSourceWhenDeleted)
: source (source_, deleteSourceWhenDeleted),
requiredNumberOfChannels (2),
buffer (2, 16)
{
remappedInfo.buffer = &buffer;
remappedInfo.startSample = 0;
}
ChannelRemappingAudioSource::~ChannelRemappingAudioSource() {}
//==============================================================================
void ChannelRemappingAudioSource::setNumberOfChannelsToProduce (const int requiredNumberOfChannels_)
{
const ScopedLock sl (lock);
requiredNumberOfChannels = requiredNumberOfChannels_;
}
void ChannelRemappingAudioSource::clearAllMappings()
{
const ScopedLock sl (lock);
remappedInputs.clear();
remappedOutputs.clear();
}
void ChannelRemappingAudioSource::setInputChannelMapping (const int destIndex, const int sourceIndex)
{
const ScopedLock sl (lock);
while (remappedInputs.size() < destIndex)
remappedInputs.add (-1);
remappedInputs.set (destIndex, sourceIndex);
}
void ChannelRemappingAudioSource::setOutputChannelMapping (const int sourceIndex, const int destIndex)
{
const ScopedLock sl (lock);
while (remappedOutputs.size() < sourceIndex)
remappedOutputs.add (-1);
remappedOutputs.set (sourceIndex, destIndex);
}
int ChannelRemappingAudioSource::getRemappedInputChannel (const int inputChannelIndex) const
{
const ScopedLock sl (lock);
if (inputChannelIndex >= 0 && inputChannelIndex < remappedInputs.size())
return remappedInputs.getUnchecked (inputChannelIndex);
return -1;
}
int ChannelRemappingAudioSource::getRemappedOutputChannel (const int outputChannelIndex) const
{
const ScopedLock sl (lock);
if (outputChannelIndex >= 0 && outputChannelIndex < remappedOutputs.size())
return remappedOutputs .getUnchecked (outputChannelIndex);
return -1;
}
//==============================================================================
void ChannelRemappingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
source->prepareToPlay (samplesPerBlockExpected, sampleRate);
}
void ChannelRemappingAudioSource::releaseResources()
{
source->releaseResources();
}
void ChannelRemappingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
const ScopedLock sl (lock);
buffer.setSize (requiredNumberOfChannels, bufferToFill.numSamples, false, false, true);
const int numChans = bufferToFill.buffer->getNumChannels();
for (int i = 0; i < buffer.getNumChannels(); ++i)
{
const int remappedChan = getRemappedInputChannel (i);
if (remappedChan >= 0 && remappedChan < numChans)
{
buffer.copyFrom (i, 0, *bufferToFill.buffer,
remappedChan,
bufferToFill.startSample,
bufferToFill.numSamples);
}
else
{
buffer.clear (i, 0, bufferToFill.numSamples);
}
}
remappedInfo.numSamples = bufferToFill.numSamples;
source->getNextAudioBlock (remappedInfo);
bufferToFill.clearActiveBufferRegion();
for (int i = 0; i < requiredNumberOfChannels; ++i)
{
const int remappedChan = getRemappedOutputChannel (i);
if (remappedChan >= 0 && remappedChan < numChans)
{
bufferToFill.buffer->addFrom (remappedChan, bufferToFill.startSample,
buffer, i, 0, bufferToFill.numSamples);
}
}
}
//==============================================================================
XmlElement* ChannelRemappingAudioSource::createXml() const
{
XmlElement* e = new XmlElement ("MAPPINGS");
String ins, outs;
const ScopedLock sl (lock);
for (int i = 0; i < remappedInputs.size(); ++i)
ins << remappedInputs.getUnchecked(i) << ' ';
for (int i = 0; i < remappedOutputs.size(); ++i)
outs << remappedOutputs.getUnchecked(i) << ' ';
e->setAttribute ("inputs", ins.trimEnd());
e->setAttribute ("outputs", outs.trimEnd());
return e;
}
void ChannelRemappingAudioSource::restoreFromXml (const XmlElement& e)
{
if (e.hasTagName ("MAPPINGS"))
{
const ScopedLock sl (lock);
clearAllMappings();
StringArray ins, outs;
ins.addTokens (e.getStringAttribute ("inputs"), false);
outs.addTokens (e.getStringAttribute ("outputs"), false);
for (int i = 0; i < ins.size(); ++i)
remappedInputs.add (ins[i].getIntValue());
for (int i = 0; i < outs.size(); ++i)
remappedOutputs.add (outs[i].getIntValue());
}
}

+ 149
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.h View File

@@ -0,0 +1,149 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__
#define __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__
#include "juce_AudioSource.h"
//==============================================================================
/**
An AudioSource that takes the audio from another source, and re-maps its
input and output channels to a different arrangement.
You can use this to increase or decrease the number of channels that an
audio source uses, or to re-order those channels.
Call the reset() method before using it to set up a default mapping, and then
the setInputChannelMapping() and setOutputChannelMapping() methods to
create an appropriate mapping, otherwise no channels will be connected and
it'll produce silence.
@see AudioSource
*/
class ChannelRemappingAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a remapping source that will pass on audio from the given input.
@param source the input source to use. Make sure that this doesn't
get deleted before the ChannelRemappingAudioSource object
@param deleteSourceWhenDeleted if true, the input source will be deleted
when this object is deleted, if false, the caller is
responsible for its deletion
*/
ChannelRemappingAudioSource (AudioSource* source,
bool deleteSourceWhenDeleted);
/** Destructor. */
~ChannelRemappingAudioSource();
//==============================================================================
/** Specifies a number of channels that this audio source must produce from its
getNextAudioBlock() callback.
*/
void setNumberOfChannelsToProduce (int requiredNumberOfChannels);
/** Clears any mapped channels.
After this, no channels are mapped, so this object will produce silence. Create
some mappings with setInputChannelMapping() and setOutputChannelMapping().
*/
void clearAllMappings();
/** Creates an input channel mapping.
When the getNextAudioBlock() method is called, the data in channel sourceChannelIndex of the incoming
data will be sent to destChannelIndex of our input source.
@param destChannelIndex the index of an input channel in our input audio source (i.e. the
source specified when this object was created).
@param sourceChannelIndex the index of the input channel in the incoming audio data buffer
during our getNextAudioBlock() callback
*/
void setInputChannelMapping (int destChannelIndex,
int sourceChannelIndex);
/** Creates an output channel mapping.
When the getNextAudioBlock() method is called, the data returned in channel sourceChannelIndex by
our input audio source will be copied to channel destChannelIndex of the final buffer.
@param sourceChannelIndex the index of an output channel coming from our input audio source
(i.e. the source specified when this object was created).
@param destChannelIndex the index of the output channel in the incoming audio data buffer
during our getNextAudioBlock() callback
*/
void setOutputChannelMapping (int sourceChannelIndex,
int destChannelIndex);
/** Returns the channel from our input that will be sent to channel inputChannelIndex of
our input audio source.
*/
int getRemappedInputChannel (int inputChannelIndex) const;
/** Returns the output channel to which channel outputChannelIndex of our input audio
source will be sent to.
*/
int getRemappedOutputChannel (int outputChannelIndex) const;
//==============================================================================
/** Returns an XML object to encapsulate the state of the mappings.
@see restoreFromXml
*/
XmlElement* createXml() const;
/** Restores the mappings from an XML object created by createXML().
@see createXml
*/
void restoreFromXml (const XmlElement& e);
//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
void releaseResources();
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);
private:
//==============================================================================
OptionalScopedPointer<AudioSource> source;
Array <int> remappedInputs, remappedOutputs;
int requiredNumberOfChannels;
AudioSampleBuffer buffer;
AudioSourceChannelInfo remappedInfo;
CriticalSection lock;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChannelRemappingAudioSource)
};
#endif // __JUCE_CHANNELREMAPPINGAUDIOSOURCE_JUCEHEADER__

+ 72
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp View File

@@ -0,0 +1,72 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
IIRFilterAudioSource::IIRFilterAudioSource (AudioSource* const inputSource,
const bool deleteInputWhenDeleted)
: input (inputSource, deleteInputWhenDeleted)
{
jassert (inputSource != nullptr);
for (int i = 2; --i >= 0;)
iirFilters.add (new IIRFilter());
}
IIRFilterAudioSource::~IIRFilterAudioSource() {}
//==============================================================================
void IIRFilterAudioSource::setFilterParameters (const IIRFilter& newSettings)
{
for (int i = iirFilters.size(); --i >= 0;)
iirFilters.getUnchecked(i)->copyCoefficientsFrom (newSettings);
}
//==============================================================================
void IIRFilterAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
input->prepareToPlay (samplesPerBlockExpected, sampleRate);
for (int i = iirFilters.size(); --i >= 0;)
iirFilters.getUnchecked(i)->reset();
}
void IIRFilterAudioSource::releaseResources()
{
input->releaseResources();
}
void IIRFilterAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
input->getNextAudioBlock (bufferToFill);
const int numChannels = bufferToFill.buffer->getNumChannels();
while (numChannels > iirFilters.size())
iirFilters.add (new IIRFilter (*iirFilters.getUnchecked (0)));
for (int i = 0; i < numChannels; ++i)
iirFilters.getUnchecked(i)
->processSamples (bufferToFill.buffer->getSampleData (i, bufferToFill.startSample),
bufferToFill.numSamples);
}

+ 71
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h View File

@@ -0,0 +1,71 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_IIRFILTERAUDIOSOURCE_JUCEHEADER__
#define __JUCE_IIRFILTERAUDIOSOURCE_JUCEHEADER__
#include "juce_AudioSource.h"
#include "../effects/juce_IIRFilter.h"
//==============================================================================
/**
An AudioSource that performs an IIR filter on another source.
*/
class JUCE_API IIRFilterAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a IIRFilterAudioSource for a given input source.
@param inputSource the input source to read from - this must not be null
@param deleteInputWhenDeleted if true, the input source will be deleted when
this object is deleted
*/
IIRFilterAudioSource (AudioSource* inputSource,
bool deleteInputWhenDeleted);
/** Destructor. */
~IIRFilterAudioSource();
//==============================================================================
/** Changes the filter to use the same parameters as the one being passed in. */
void setFilterParameters (const IIRFilter& newSettings);
//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
void releaseResources();
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);
private:
//==============================================================================
OptionalScopedPointer<AudioSource> input;
OwnedArray <IIRFilter> iirFilters;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (IIRFilterAudioSource)
};
#endif // __JUCE_IIRFILTERAUDIOSOURCE_JUCEHEADER__

+ 158
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp View File

@@ -0,0 +1,158 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
MixerAudioSource::MixerAudioSource()
: tempBuffer (2, 0),
currentSampleRate (0.0),
bufferSizeExpected (0)
{
}
MixerAudioSource::~MixerAudioSource()
{
removeAllInputs();
}
//==============================================================================
void MixerAudioSource::addInputSource (AudioSource* input, const bool deleteWhenRemoved)
{
if (input != nullptr && ! inputs.contains (input))
{
double localRate;
int localBufferSize;
{
const ScopedLock sl (lock);
localRate = currentSampleRate;
localBufferSize = bufferSizeExpected;
}
if (localRate > 0.0)
input->prepareToPlay (localBufferSize, localRate);
const ScopedLock sl (lock);
inputsToDelete.setBit (inputs.size(), deleteWhenRemoved);
inputs.add (input);
}
}
void MixerAudioSource::removeInputSource (AudioSource* const input)
{
if (input != nullptr)
{
ScopedPointer<AudioSource> toDelete;
{
const ScopedLock sl (lock);
const int index = inputs.indexOf (input);
if (index < 0)
return;
if (inputsToDelete [index])
toDelete = input;
inputsToDelete.shiftBits (-1, index);
inputs.remove (index);
}
input->releaseResources();
}
}
void MixerAudioSource::removeAllInputs()
{
OwnedArray<AudioSource> toDelete;
{
const ScopedLock sl (lock);
for (int i = inputs.size(); --i >= 0;)
if (inputsToDelete[i])
toDelete.add (inputs.getUnchecked(i));
inputs.clear();
}
for (int i = toDelete.size(); --i >= 0;)
toDelete.getUnchecked(i)->releaseResources();
}
void MixerAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
tempBuffer.setSize (2, samplesPerBlockExpected);
const ScopedLock sl (lock);
currentSampleRate = sampleRate;
bufferSizeExpected = samplesPerBlockExpected;
for (int i = inputs.size(); --i >= 0;)
inputs.getUnchecked(i)->prepareToPlay (samplesPerBlockExpected, sampleRate);
}
void MixerAudioSource::releaseResources()
{
const ScopedLock sl (lock);
for (int i = inputs.size(); --i >= 0;)
inputs.getUnchecked(i)->releaseResources();
tempBuffer.setSize (2, 0);
currentSampleRate = 0;
bufferSizeExpected = 0;
}
void MixerAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
const ScopedLock sl (lock);
if (inputs.size() > 0)
{
inputs.getUnchecked(0)->getNextAudioBlock (info);
if (inputs.size() > 1)
{
tempBuffer.setSize (jmax (1, info.buffer->getNumChannels()),
info.buffer->getNumSamples());
AudioSourceChannelInfo info2 (&tempBuffer, 0, info.numSamples);
for (int i = 1; i < inputs.size(); ++i)
{
inputs.getUnchecked(i)->getNextAudioBlock (info2);
for (int chan = 0; chan < info.buffer->getNumChannels(); ++chan)
info.buffer->addFrom (chan, info.startSample, tempBuffer, chan, 0, info.numSamples);
}
}
}
else
{
info.clearActiveBufferRegion();
}
}

+ 104
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.h View File

@@ -0,0 +1,104 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__
#define __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__
#include "juce_AudioSource.h"
//==============================================================================
/**
An AudioSource that mixes together the output of a set of other AudioSources.
Input sources can be added and removed while the mixer is running as long as their
prepareToPlay() and releaseResources() methods are called before and after adding
them to the mixer.
*/
class JUCE_API MixerAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a MixerAudioSource. */
MixerAudioSource();
/** Destructor. */
~MixerAudioSource();
//==============================================================================
/** Adds an input source to the mixer.
If the mixer is running you'll need to make sure that the input source
is ready to play by calling its prepareToPlay() method before adding it.
If the mixer is stopped, then its input sources will be automatically
prepared when the mixer's prepareToPlay() method is called.
@param newInput the source to add to the mixer
@param deleteWhenRemoved if true, then this source will be deleted when
no longer needed by the mixer.
*/
void addInputSource (AudioSource* newInput, bool deleteWhenRemoved);
/** Removes an input source.
If the source was added by calling addInputSource() with the deleteWhenRemoved
flag set, it will be deleted by this method.
*/
void removeInputSource (AudioSource* input);
/** Removes all the input sources.
Any sources which were added by calling addInputSource() with the deleteWhenRemoved
flag set will be deleted by this method.
*/
void removeAllInputs();
//==============================================================================
/** Implementation of the AudioSource method.
This will call prepareToPlay() on all its input sources.
*/
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
/** Implementation of the AudioSource method.
This will call releaseResources() on all its input sources.
*/
void releaseResources();
/** Implementation of the AudioSource method. */
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);
private:
//==============================================================================
Array <AudioSource*> inputs;
BigInteger inputsToDelete;
CriticalSection lock;
AudioSampleBuffer tempBuffer;
double currentSampleRate;
int bufferSizeExpected;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MixerAudioSource)
};
#endif // __JUCE_MIXERAUDIOSOURCE_JUCEHEADER__

+ 81
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_PositionableAudioSource.h View File

@@ -0,0 +1,81 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__
#define __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__
#include "juce_AudioSource.h"
//==============================================================================
/**
A type of AudioSource which can be repositioned.
The basic AudioSource just streams continuously with no idea of a current
time or length, so the PositionableAudioSource is used for a finite stream
that has a current read position.
@see AudioSource, AudioTransportSource
*/
class JUCE_API PositionableAudioSource : public AudioSource
{
protected:
//==============================================================================
/** Creates the PositionableAudioSource. */
PositionableAudioSource() noexcept {}
public:
/** Destructor */
~PositionableAudioSource() {}
//==============================================================================
/** Tells the stream to move to a new position.
Calling this indicates that the next call to AudioSource::getNextAudioBlock()
should return samples from this position.
Note that this may be called on a different thread to getNextAudioBlock(),
so the subclass should make sure it's synchronised.
*/
virtual void setNextReadPosition (int64 newPosition) = 0;
/** Returns the position from which the next block will be returned.
@see setNextReadPosition
*/
virtual int64 getNextReadPosition() const = 0;
/** Returns the total length of the stream (in samples). */
virtual int64 getTotalLength() const = 0;
/** Returns true if this source is actually playing in a loop. */
virtual bool isLooping() const = 0;
/** Tells the source whether you'd like it to play in a loop. */
virtual void setLooping (bool shouldLoop) { (void) shouldLoop; }
};
#endif // __JUCE_POSITIONABLEAUDIOSOURCE_JUCEHEADER__

+ 254
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp View File

@@ -0,0 +1,254 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
ResamplingAudioSource::ResamplingAudioSource (AudioSource* const inputSource,
const bool deleteInputWhenDeleted,
const int numChannels_)
: input (inputSource, deleteInputWhenDeleted),
ratio (1.0),
lastRatio (1.0),
buffer (numChannels_, 0),
sampsInBuffer (0),
numChannels (numChannels_)
{
jassert (input != nullptr);
}
ResamplingAudioSource::~ResamplingAudioSource() {}
void ResamplingAudioSource::setResamplingRatio (const double samplesInPerOutputSample)
{
jassert (samplesInPerOutputSample > 0);
const SpinLock::ScopedLockType sl (ratioLock);
ratio = jmax (0.0, samplesInPerOutputSample);
}
void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected,
double sampleRate)
{
const SpinLock::ScopedLockType sl (ratioLock);
input->prepareToPlay (samplesPerBlockExpected, sampleRate);
buffer.setSize (numChannels, roundToInt (samplesPerBlockExpected * ratio) + 32);
buffer.clear();
sampsInBuffer = 0;
bufferPos = 0;
subSampleOffset = 0.0;
filterStates.calloc ((size_t) numChannels);
srcBuffers.calloc ((size_t) numChannels);
destBuffers.calloc ((size_t) numChannels);
createLowPass (ratio);
resetFilters();
}
void ResamplingAudioSource::releaseResources()
{
input->releaseResources();
buffer.setSize (numChannels, 0);
}
void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
double localRatio;
{
const SpinLock::ScopedLockType sl (ratioLock);
localRatio = ratio;
}
if (lastRatio != localRatio)
{
createLowPass (localRatio);
lastRatio = localRatio;
}
const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 2;
int bufferSize = buffer.getNumSamples();
if (bufferSize < sampsNeeded + 8)
{
bufferPos %= bufferSize;
bufferSize = sampsNeeded + 32;
buffer.setSize (buffer.getNumChannels(), bufferSize, true, true);
}
bufferPos %= bufferSize;
int endOfBufferPos = bufferPos + sampsInBuffer;
const int channelsToProcess = jmin (numChannels, info.buffer->getNumChannels());
while (sampsNeeded > sampsInBuffer)
{
endOfBufferPos %= bufferSize;
int numToDo = jmin (sampsNeeded - sampsInBuffer,
bufferSize - endOfBufferPos);
AudioSourceChannelInfo readInfo (&buffer, endOfBufferPos, numToDo);
input->getNextAudioBlock (readInfo);
if (localRatio > 1.0001)
{
// for down-sampling, pre-apply the filter..
for (int i = channelsToProcess; --i >= 0;)
applyFilter (buffer.getSampleData (i, endOfBufferPos), numToDo, filterStates[i]);
}
sampsInBuffer += numToDo;
endOfBufferPos += numToDo;
}
for (int channel = 0; channel < channelsToProcess; ++channel)
{
destBuffers[channel] = info.buffer->getSampleData (channel, info.startSample);
srcBuffers[channel] = buffer.getSampleData (channel, 0);
}
int nextPos = (bufferPos + 1) % bufferSize;
for (int m = info.numSamples; --m >= 0;)
{
const float alpha = (float) subSampleOffset;
for (int channel = 0; channel < channelsToProcess; ++channel)
*destBuffers[channel]++ = srcBuffers[channel][bufferPos]
+ alpha * (srcBuffers[channel][nextPos] - srcBuffers[channel][bufferPos]);
subSampleOffset += localRatio;
jassert (sampsInBuffer > 0);
while (subSampleOffset >= 1.0)
{
if (++bufferPos >= bufferSize)
bufferPos = 0;
--sampsInBuffer;
nextPos = (bufferPos + 1) % bufferSize;
subSampleOffset -= 1.0;
}
}
if (localRatio < 0.9999)
{
// for up-sampling, apply the filter after transposing..
for (int i = channelsToProcess; --i >= 0;)
applyFilter (info.buffer->getSampleData (i, info.startSample), info.numSamples, filterStates[i]);
}
else if (localRatio <= 1.0001 && info.numSamples > 0)
{
// if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities
for (int i = channelsToProcess; --i >= 0;)
{
const float* const endOfBuffer = info.buffer->getSampleData (i, info.startSample + info.numSamples - 1);
FilterState& fs = filterStates[i];
if (info.numSamples > 1)
{
fs.y2 = fs.x2 = *(endOfBuffer - 1);
}
else
{
fs.y2 = fs.y1;
fs.x2 = fs.x1;
}
fs.y1 = fs.x1 = *endOfBuffer;
}
}
jassert (sampsInBuffer >= 0);
}
void ResamplingAudioSource::createLowPass (const double frequencyRatio)
{
const double proportionalRate = (frequencyRatio > 1.0) ? 0.5 / frequencyRatio
: 0.5 * frequencyRatio;
const double n = 1.0 / std::tan (double_Pi * jmax (0.001, proportionalRate));
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
setFilterCoefficients (c1,
c1 * 2.0f,
c1,
1.0,
c1 * 2.0 * (1.0 - nSquared),
c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
}
void ResamplingAudioSource::setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6)
{
const double a = 1.0 / c4;
c1 *= a;
c2 *= a;
c3 *= a;
c5 *= a;
c6 *= a;
coefficients[0] = c1;
coefficients[1] = c2;
coefficients[2] = c3;
coefficients[3] = c4;
coefficients[4] = c5;
coefficients[5] = c6;
}
void ResamplingAudioSource::resetFilters()
{
filterStates.clear ((size_t) numChannels);
}
void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs)
{
while (--num >= 0)
{
const double in = *samples;
double out = coefficients[0] * in
+ coefficients[1] * fs.x1
+ coefficients[2] * fs.x2
- coefficients[4] * fs.y1
- coefficients[5] * fs.y2;
#if JUCE_INTEL
if (! (out < -1.0e-8 || out > 1.0e-8))
out = 0;
#endif
fs.x2 = fs.x1;
fs.x1 = in;
fs.y2 = fs.y1;
fs.y1 = out;
*samples++ = (float) out;
}
}

+ 106
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h View File

@@ -0,0 +1,106 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__
#define __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__
#include "juce_AudioSource.h"
//==============================================================================
/**
A type of AudioSource that takes an input source and changes its sample rate.
@see AudioSource
*/
class JUCE_API ResamplingAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a ResamplingAudioSource for a given input source.
@param inputSource the input source to read from
@param deleteInputWhenDeleted if true, the input source will be deleted when
this object is deleted
@param numChannels the number of channels to process
*/
ResamplingAudioSource (AudioSource* inputSource,
bool deleteInputWhenDeleted,
int numChannels = 2);
/** Destructor. */
~ResamplingAudioSource();
/** Changes the resampling ratio.
(This value can be changed at any time, even while the source is running).
@param samplesInPerOutputSample if set to 1.0, the input is passed through; higher
values will speed it up; lower values will slow it
down. The ratio must be greater than 0
*/
void setResamplingRatio (double samplesInPerOutputSample);
/** Returns the current resampling ratio.
This is the value that was set by setResamplingRatio().
*/
double getResamplingRatio() const noexcept { return ratio; }
//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
void releaseResources();
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);
private:
//==============================================================================
OptionalScopedPointer<AudioSource> input;
double ratio, lastRatio;
AudioSampleBuffer buffer;
int bufferPos, sampsInBuffer;
double subSampleOffset;
double coefficients[6];
SpinLock ratioLock;
const int numChannels;
HeapBlock<float*> destBuffers, srcBuffers;
void setFilterCoefficients (double c1, double c2, double c3, double c4, double c5, double c6);
void createLowPass (double proportionalRate);
struct FilterState
{
double x1, x2, y1, y2;
};
HeapBlock<FilterState> filterStates;
void resetFilters();
void applyFilter (float* samples, int num, FilterState& fs);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ResamplingAudioSource)
};
#endif // __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__

+ 81
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp View File

@@ -0,0 +1,81 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
ReverbAudioSource::ReverbAudioSource (AudioSource* const inputSource, const bool deleteInputWhenDeleted)
: input (inputSource, deleteInputWhenDeleted),
bypass (false)
{
jassert (inputSource != nullptr);
}
ReverbAudioSource::~ReverbAudioSource() {}
void ReverbAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
const ScopedLock sl (lock);
input->prepareToPlay (samplesPerBlockExpected, sampleRate);
reverb.setSampleRate (sampleRate);
}
void ReverbAudioSource::releaseResources() {}
void ReverbAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill)
{
const ScopedLock sl (lock);
input->getNextAudioBlock (bufferToFill);
if (! bypass)
{
float* const firstChannel = bufferToFill.buffer->getSampleData (0, bufferToFill.startSample);
if (bufferToFill.buffer->getNumChannels() > 1)
{
reverb.processStereo (firstChannel,
bufferToFill.buffer->getSampleData (1, bufferToFill.startSample),
bufferToFill.numSamples);
}
else
{
reverb.processMono (firstChannel, bufferToFill.numSamples);
}
}
}
void ReverbAudioSource::setParameters (const Reverb::Parameters& newParams)
{
const ScopedLock sl (lock);
reverb.setParameters (newParams);
}
void ReverbAudioSource::setBypassed (bool b) noexcept
{
if (bypass != b)
{
const ScopedLock sl (lock);
bypass = b;
reverb.reset();
}
}

+ 80
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.h View File

@@ -0,0 +1,80 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_REVERBAUDIOSOURCE_JUCEHEADER__
#define __JUCE_REVERBAUDIOSOURCE_JUCEHEADER__
#include "juce_AudioSource.h"
#include "../effects/juce_Reverb.h"
//==============================================================================
/**
An AudioSource that uses the Reverb class to apply a reverb to another AudioSource.
@see Reverb
*/
class JUCE_API ReverbAudioSource : public AudioSource
{
public:
/** Creates a ReverbAudioSource to process a given input source.
@param inputSource the input source to read from - this must not be null
@param deleteInputWhenDeleted if true, the input source will be deleted when
this object is deleted
*/
ReverbAudioSource (AudioSource* inputSource,
bool deleteInputWhenDeleted);
/** Destructor. */
~ReverbAudioSource();
//==============================================================================
/** Returns the parameters from the reverb. */
const Reverb::Parameters& getParameters() const noexcept { return reverb.getParameters(); }
/** Changes the reverb's parameters. */
void setParameters (const Reverb::Parameters& newParams);
void setBypassed (bool isBypassed) noexcept;
bool isBypassed() const noexcept { return bypass; }
//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
void releaseResources();
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);
private:
//==============================================================================
CriticalSection lock;
OptionalScopedPointer<AudioSource> input;
Reverb reverb;
volatile bool bypass;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ReverbAudioSource)
};
#endif // __JUCE_REVERBAUDIOSOURCE_JUCEHEADER__

+ 77
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp View File

@@ -0,0 +1,77 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
ToneGeneratorAudioSource::ToneGeneratorAudioSource()
: frequency (1000.0),
sampleRate (44100.0),
currentPhase (0.0),
phasePerSample (0.0),
amplitude (0.5f)
{
}
ToneGeneratorAudioSource::~ToneGeneratorAudioSource()
{
}
//==============================================================================
void ToneGeneratorAudioSource::setAmplitude (const float newAmplitude)
{
amplitude = newAmplitude;
}
void ToneGeneratorAudioSource::setFrequency (const double newFrequencyHz)
{
frequency = newFrequencyHz;
phasePerSample = 0.0;
}
//==============================================================================
void ToneGeneratorAudioSource::prepareToPlay (int /*samplesPerBlockExpected*/,
double sampleRate_)
{
currentPhase = 0.0;
phasePerSample = 0.0;
sampleRate = sampleRate_;
}
void ToneGeneratorAudioSource::releaseResources()
{
}
void ToneGeneratorAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
if (phasePerSample == 0.0)
phasePerSample = double_Pi * 2.0 / (sampleRate / frequency);
for (int i = 0; i < info.numSamples; ++i)
{
const float sample = amplitude * (float) std::sin (currentPhase);
currentPhase += phasePerSample;
for (int j = info.buffer->getNumChannels(); --j >= 0;)
*info.buffer->getSampleData (j, info.startSample + i) = sample;
}
}

+ 76
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.h View File

@@ -0,0 +1,76 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__
#define __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__
#include "juce_AudioSource.h"
//==============================================================================
/**
A simple AudioSource that generates a sine wave.
*/
class JUCE_API ToneGeneratorAudioSource : public AudioSource
{
public:
//==============================================================================
/** Creates a ToneGeneratorAudioSource. */
ToneGeneratorAudioSource();
/** Destructor. */
~ToneGeneratorAudioSource();
//==============================================================================
/** Sets the signal's amplitude. */
void setAmplitude (float newAmplitude);
/** Sets the signal's frequency. */
void setFrequency (double newFrequencyHz);
//==============================================================================
/** Implementation of the AudioSource method. */
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
/** Implementation of the AudioSource method. */
void releaseResources();
/** Implementation of the AudioSource method. */
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);
private:
//==============================================================================
double frequency, sampleRate;
double currentPhase, phasePerSample;
float amplitude;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ToneGeneratorAudioSource)
};
#endif // __JUCE_TONEGENERATORAUDIOSOURCE_JUCEHEADER__

+ 433
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp View File

@@ -0,0 +1,433 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
SynthesiserSound::SynthesiserSound()
{
}
SynthesiserSound::~SynthesiserSound()
{
}
//==============================================================================
SynthesiserVoice::SynthesiserVoice()
: currentSampleRate (44100.0),
currentlyPlayingNote (-1),
noteOnTime (0),
keyIsDown (false),
sostenutoPedalDown (false)
{
}
SynthesiserVoice::~SynthesiserVoice()
{
}
bool SynthesiserVoice::isPlayingChannel (const int midiChannel) const
{
return currentlyPlayingSound != nullptr
&& currentlyPlayingSound->appliesToChannel (midiChannel);
}
void SynthesiserVoice::setCurrentPlaybackSampleRate (const double newRate)
{
currentSampleRate = newRate;
}
void SynthesiserVoice::clearCurrentNote()
{
currentlyPlayingNote = -1;
currentlyPlayingSound = nullptr;
}
//==============================================================================
Synthesiser::Synthesiser()
: sampleRate (0),
lastNoteOnCounter (0),
shouldStealNotes (true)
{
for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i)
lastPitchWheelValues[i] = 0x2000;
}
Synthesiser::~Synthesiser()
{
}
//==============================================================================
SynthesiserVoice* Synthesiser::getVoice (const int index) const
{
const ScopedLock sl (lock);
return voices [index];
}
void Synthesiser::clearVoices()
{
const ScopedLock sl (lock);
voices.clear();
}
void Synthesiser::addVoice (SynthesiserVoice* const newVoice)
{
const ScopedLock sl (lock);
voices.add (newVoice);
}
void Synthesiser::removeVoice (const int index)
{
const ScopedLock sl (lock);
voices.remove (index);
}
void Synthesiser::clearSounds()
{
const ScopedLock sl (lock);
sounds.clear();
}
void Synthesiser::addSound (const SynthesiserSound::Ptr& newSound)
{
const ScopedLock sl (lock);
sounds.add (newSound);
}
void Synthesiser::removeSound (const int index)
{
const ScopedLock sl (lock);
sounds.remove (index);
}
void Synthesiser::setNoteStealingEnabled (const bool shouldStealNotes_)
{
shouldStealNotes = shouldStealNotes_;
}
//==============================================================================
void Synthesiser::setCurrentPlaybackSampleRate (const double newRate)
{
if (sampleRate != newRate)
{
const ScopedLock sl (lock);
allNotesOff (0, false);
sampleRate = newRate;
for (int i = voices.size(); --i >= 0;)
voices.getUnchecked (i)->setCurrentPlaybackSampleRate (newRate);
}
}
void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer,
const MidiBuffer& midiData,
int startSample,
int numSamples)
{
// must set the sample rate before using this!
jassert (sampleRate != 0);
const ScopedLock sl (lock);
MidiBuffer::Iterator midiIterator (midiData);
midiIterator.setNextSamplePosition (startSample);
MidiMessage m (0xf4, 0.0);
while (numSamples > 0)
{
int midiEventPos;
const bool useEvent = midiIterator.getNextEvent (m, midiEventPos)
&& midiEventPos < startSample + numSamples;
const int numThisTime = useEvent ? midiEventPos - startSample
: numSamples;
if (numThisTime > 0)
{
for (int i = voices.size(); --i >= 0;)
voices.getUnchecked (i)->renderNextBlock (outputBuffer, startSample, numThisTime);
}
if (useEvent)
handleMidiEvent (m);
startSample += numThisTime;
numSamples -= numThisTime;
}
}
void Synthesiser::handleMidiEvent (const MidiMessage& m)
{
if (m.isNoteOn())
{
noteOn (m.getChannel(),
m.getNoteNumber(),
m.getFloatVelocity());
}
else if (m.isNoteOff())
{
noteOff (m.getChannel(),
m.getNoteNumber(),
true);
}
else if (m.isAllNotesOff() || m.isAllSoundOff())
{
allNotesOff (m.getChannel(), true);
}
else if (m.isPitchWheel())
{
const int channel = m.getChannel();
const int wheelPos = m.getPitchWheelValue();
lastPitchWheelValues [channel - 1] = wheelPos;
handlePitchWheel (channel, wheelPos);
}
else if (m.isController())
{
handleController (m.getChannel(),
m.getControllerNumber(),
m.getControllerValue());
}
}
//==============================================================================
void Synthesiser::noteOn (const int midiChannel,
const int midiNoteNumber,
const float velocity)
{
const ScopedLock sl (lock);
for (int i = sounds.size(); --i >= 0;)
{
SynthesiserSound* const sound = sounds.getUnchecked(i);
if (sound->appliesToNote (midiNoteNumber)
&& sound->appliesToChannel (midiChannel))
{
// If hitting a note that's still ringing, stop it first (it could be
// still playing because of the sustain or sostenuto pedal).
for (int j = voices.size(); --j >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (j);
if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& voice->isPlayingChannel (midiChannel))
stopVoice (voice, true);
}
startVoice (findFreeVoice (sound, shouldStealNotes),
sound, midiChannel, midiNoteNumber, velocity);
}
}
}
void Synthesiser::startVoice (SynthesiserVoice* const voice,
SynthesiserSound* const sound,
const int midiChannel,
const int midiNoteNumber,
const float velocity)
{
if (voice != nullptr && sound != nullptr)
{
if (voice->currentlyPlayingSound != nullptr)
voice->stopNote (false);
voice->startNote (midiNoteNumber, velocity, sound,
lastPitchWheelValues [midiChannel - 1]);
voice->currentlyPlayingNote = midiNoteNumber;
voice->noteOnTime = ++lastNoteOnCounter;
voice->currentlyPlayingSound = sound;
voice->keyIsDown = true;
voice->sostenutoPedalDown = false;
}
}
void Synthesiser::stopVoice (SynthesiserVoice* voice, const bool allowTailOff)
{
jassert (voice != nullptr);
voice->stopNote (allowTailOff);
// the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()!
jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0));
}
void Synthesiser::noteOff (const int midiChannel,
const int midiNoteNumber,
const bool allowTailOff)
{
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
{
if (SynthesiserSound* const sound = voice->getCurrentlyPlayingSound())
{
if (sound->appliesToNote (midiNoteNumber)
&& sound->appliesToChannel (midiChannel))
{
voice->keyIsDown = false;
if (! (sustainPedalsDown [midiChannel] || voice->sostenutoPedalDown))
stopVoice (voice, allowTailOff);
}
}
}
}
}
void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff)
{
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->stopNote (allowTailOff);
}
sustainPedalsDown.clear();
}
void Synthesiser::handlePitchWheel (const int midiChannel, const int wheelValue)
{
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->pitchWheelMoved (wheelValue);
}
}
void Synthesiser::handleController (const int midiChannel,
const int controllerNumber,
const int controllerValue)
{
switch (controllerNumber)
{
case 0x40: handleSustainPedal (midiChannel, controllerValue >= 64); break;
case 0x42: handleSostenutoPedal (midiChannel, controllerValue >= 64); break;
case 0x43: handleSoftPedal (midiChannel, controllerValue >= 64); break;
default: break;
}
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->controllerMoved (controllerNumber, controllerValue);
}
}
void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
{
jassert (midiChannel > 0 && midiChannel <= 16);
const ScopedLock sl (lock);
if (isDown)
{
sustainPedalsDown.setBit (midiChannel);
}
else
{
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->isPlayingChannel (midiChannel) && ! voice->keyIsDown)
stopVoice (voice, true);
}
sustainPedalsDown.clearBit (midiChannel);
}
}
void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
{
jassert (midiChannel > 0 && midiChannel <= 16);
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->isPlayingChannel (midiChannel))
{
if (isDown)
voice->sostenutoPedalDown = true;
else if (voice->sostenutoPedalDown)
stopVoice (voice, true);
}
}
}
void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/)
{
(void) midiChannel;
jassert (midiChannel > 0 && midiChannel <= 16);
}
//==============================================================================
SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
const bool stealIfNoneAvailable) const
{
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
if (voices.getUnchecked (i)->getCurrentlyPlayingNote() < 0
&& voices.getUnchecked (i)->canPlaySound (soundToPlay))
return voices.getUnchecked (i);
if (stealIfNoneAvailable)
{
// currently this just steals the one that's been playing the longest, but could be made a bit smarter..
SynthesiserVoice* oldest = nullptr;
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->canPlaySound (soundToPlay)
&& (oldest == nullptr || oldest->noteOnTime > voice->noteOnTime))
oldest = voice;
}
jassert (oldest != nullptr);
return oldest;
}
return nullptr;
}

+ 494
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h View File

@@ -0,0 +1,494 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_SYNTHESISER_JUCEHEADER__
#define __JUCE_SYNTHESISER_JUCEHEADER__
#include "../buffers/juce_AudioSampleBuffer.h"
#include "../midi/juce_MidiBuffer.h"
//==============================================================================
/**
Describes one of the sounds that a Synthesiser can play.
A synthesiser can contain one or more sounds, and a sound can choose which
midi notes and channels can trigger it.
The SynthesiserSound is a passive class that just describes what the sound is -
the actual audio rendering for a sound is done by a SynthesiserVoice. This allows
more than one SynthesiserVoice to play the same sound at the same time.
@see Synthesiser, SynthesiserVoice
*/
class JUCE_API SynthesiserSound : public ReferenceCountedObject
{
protected:
//==============================================================================
SynthesiserSound();
public:
/** Destructor. */
virtual ~SynthesiserSound();
//==============================================================================
/** Returns true if this sound should be played when a given midi note is pressed.
The Synthesiser will use this information when deciding which sounds to trigger
for a given note.
*/
virtual bool appliesToNote (const int midiNoteNumber) = 0;
/** Returns true if the sound should be triggered by midi events on a given channel.
The Synthesiser will use this information when deciding which sounds to trigger
for a given note.
*/
virtual bool appliesToChannel (const int midiChannel) = 0;
/**
*/
typedef ReferenceCountedObjectPtr <SynthesiserSound> Ptr;
private:
//==============================================================================
JUCE_LEAK_DETECTOR (SynthesiserSound)
};
//==============================================================================
/**
Represents a voice that a Synthesiser can use to play a SynthesiserSound.
A voice plays a single sound at a time, and a synthesiser holds an array of
voices so that it can play polyphonically.
@see Synthesiser, SynthesiserSound
*/
class JUCE_API SynthesiserVoice
{
public:
//==============================================================================
/** Creates a voice. */
SynthesiserVoice();
/** Destructor. */
virtual ~SynthesiserVoice();
//==============================================================================
/** Returns the midi note that this voice is currently playing.
Returns a value less than 0 if no note is playing.
*/
int getCurrentlyPlayingNote() const { return currentlyPlayingNote; }
/** Returns the sound that this voice is currently playing.
Returns nullptr if it's not playing.
*/
SynthesiserSound::Ptr getCurrentlyPlayingSound() const { return currentlyPlayingSound; }
/** Must return true if this voice object is capable of playing the given sound.
If there are different classes of sound, and different classes of voice, a voice can
choose which ones it wants to take on.
A typical implementation of this method may just return true if there's only one type
of voice and sound, or it might check the type of the sound object passed-in and
see if it's one that it understands.
*/
virtual bool canPlaySound (SynthesiserSound* sound) = 0;
/** Called to start a new note.
This will be called during the rendering callback, so must be fast and thread-safe.
*/
virtual void startNote (const int midiNoteNumber,
const float velocity,
SynthesiserSound* sound,
const int currentPitchWheelPosition) = 0;
/** Called to stop a note.
This will be called during the rendering callback, so must be fast and thread-safe.
If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all
sound immediately, and must call clearCurrentNote() to reset the state of this voice
and allow the synth to reassign it another sound.
If allowTailOff is true and the voice decides to do a tail-off, then it's allowed to
begin fading out its sound, and it can stop playing until it's finished. As soon as it
finishes playing (during the rendering callback), it must make sure that it calls
clearCurrentNote().
*/
virtual void stopNote (const bool allowTailOff) = 0;
/** Called to let the voice know that the pitch wheel has been moved.
This will be called during the rendering callback, so must be fast and thread-safe.
*/
virtual void pitchWheelMoved (const int newValue) = 0;
/** Called to let the voice know that a midi controller has been moved.
This will be called during the rendering callback, so must be fast and thread-safe.
*/
virtual void controllerMoved (const int controllerNumber,
const int newValue) = 0;
//==============================================================================
/** Renders the next block of data for this voice.
The output audio data must be added to the current contents of the buffer provided.
Only the region of the buffer between startSample and (startSample + numSamples)
should be altered by this method.
If the voice is currently silent, it should just return without doing anything.
If the sound that the voice is playing finishes during the course of this rendered
block, it must call clearCurrentNote(), to tell the synthesiser that it has finished.
The size of the blocks that are rendered can change each time it is called, and may
involve rendering as little as 1 sample at a time. In between rendering callbacks,
the voice's methods will be called to tell it about note and controller events.
*/
virtual void renderNextBlock (AudioSampleBuffer& outputBuffer,
int startSample,
int numSamples) = 0;
/** Returns true if the voice is currently playing a sound which is mapped to the given
midi channel.
If it's not currently playing, this will return false.
*/
bool isPlayingChannel (int midiChannel) const;
/** Changes the voice's reference sample rate.
The rate is set so that subclasses know the output rate and can set their pitch
accordingly.
This method is called by the synth, and subclasses can access the current rate with
the currentSampleRate member.
*/
void setCurrentPlaybackSampleRate (double newRate);
protected:
//==============================================================================
/** Returns the current target sample rate at which rendering is being done.
This is available for subclasses so they can pitch things correctly.
*/
double getSampleRate() const { return currentSampleRate; }
/** Resets the state of this voice after a sound has finished playing.
The subclass must call this when it finishes playing a note and becomes available
to play new ones.
It must either call it in the stopNote() method, or if the voice is tailing off,
then it should call it later during the renderNextBlock method, as soon as it
finishes its tail-off.
It can also be called at any time during the render callback if the sound happens
to have finished, e.g. if it's playing a sample and the sample finishes.
*/
void clearCurrentNote();
private:
//==============================================================================
friend class Synthesiser;
double currentSampleRate;
int currentlyPlayingNote;
uint32 noteOnTime;
SynthesiserSound::Ptr currentlyPlayingSound;
bool keyIsDown; // the voice may still be playing when the key is not down (i.e. sustain pedal)
bool sostenutoPedalDown;
JUCE_LEAK_DETECTOR (SynthesiserVoice)
};
//==============================================================================
/**
Base class for a musical device that can play sounds.
To create a synthesiser, you'll need to create a subclass of SynthesiserSound
to describe each sound available to your synth, and a subclass of SynthesiserVoice
which can play back one of these sounds.
Then you can use the addVoice() and addSound() methods to give the synthesiser a
set of sounds, and a set of voices it can use to play them. If you only give it
one voice it will be monophonic - the more voices it has, the more polyphony it'll
have available.
Then repeatedly call the renderNextBlock() method to produce the audio. Any midi
events that go in will be scanned for note on/off messages, and these are used to
start and stop the voices playing the appropriate sounds.
While it's playing, you can also cause notes to be triggered by calling the noteOn(),
noteOff() and other controller methods.
Before rendering, be sure to call the setCurrentPlaybackSampleRate() to tell it
what the target playback rate is. This value is passed on to the voices so that
they can pitch their output correctly.
*/
class JUCE_API Synthesiser
{
public:
//==============================================================================
/** Creates a new synthesiser.
You'll need to add some sounds and voices before it'll make any sound..
*/
Synthesiser();
/** Destructor. */
virtual ~Synthesiser();
//==============================================================================
/** Deletes all voices. */
void clearVoices();
/** Returns the number of voices that have been added. */
int getNumVoices() const { return voices.size(); }
/** Returns one of the voices that have been added. */
SynthesiserVoice* getVoice (int index) const;
/** Adds a new voice to the synth.
All the voices should be the same class of object and are treated equally.
The object passed in will be managed by the synthesiser, which will delete
it later on when no longer needed. The caller should not retain a pointer to the
voice.
*/
void addVoice (SynthesiserVoice* newVoice);
/** Deletes one of the voices. */
void removeVoice (int index);
//==============================================================================
/** Deletes all sounds. */
void clearSounds();
/** Returns the number of sounds that have been added to the synth. */
int getNumSounds() const { return sounds.size(); }
/** Returns one of the sounds. */
SynthesiserSound* getSound (int index) const { return sounds [index]; }
/** Adds a new sound to the synthesiser.
The object passed in is reference counted, so will be deleted when it is removed
from the synthesiser, and when no voices are still using it.
*/
void addSound (const SynthesiserSound::Ptr& newSound);
/** Removes and deletes one of the sounds. */
void removeSound (int index);
//==============================================================================
/** If set to true, then the synth will try to take over an existing voice if
it runs out and needs to play another note.
The value of this boolean is passed into findFreeVoice(), so the result will
depend on the implementation of this method.
*/
void setNoteStealingEnabled (bool shouldStealNotes);
/** Returns true if note-stealing is enabled.
@see setNoteStealingEnabled
*/
bool isNoteStealingEnabled() const { return shouldStealNotes; }
//==============================================================================
/** Triggers a note-on event.
The default method here will find all the sounds that want to be triggered by
this note/channel. For each sound, it'll try to find a free voice, and use the
voice to start playing the sound.
Subclasses might want to override this if they need a more complex algorithm.
This method will be called automatically according to the midi data passed into
renderNextBlock(), but may be called explicitly too.
The midiChannel parameter is the channel, between 1 and 16 inclusive.
*/
virtual void noteOn (int midiChannel,
int midiNoteNumber,
float velocity);
/** Triggers a note-off event.
This will turn off any voices that are playing a sound for the given note/channel.
If allowTailOff is true, the voices will be allowed to fade out the notes gracefully
(if they can do). If this is false, the notes will all be cut off immediately.
This method will be called automatically according to the midi data passed into
renderNextBlock(), but may be called explicitly too.
The midiChannel parameter is the channel, between 1 and 16 inclusive.
*/
virtual void noteOff (int midiChannel,
int midiNoteNumber,
bool allowTailOff);
/** Turns off all notes.
This will turn off any voices that are playing a sound on the given midi channel.
If midiChannel is 0 or less, then all voices will be turned off, regardless of
which channel they're playing. Otherwise it represents a valid midi channel, from
1 to 16 inclusive.
If allowTailOff is true, the voices will be allowed to fade out the notes gracefully
(if they can do). If this is false, the notes will all be cut off immediately.
This method will be called automatically according to the midi data passed into
renderNextBlock(), but may be called explicitly too.
*/
virtual void allNotesOff (int midiChannel,
bool allowTailOff);
/** Sends a pitch-wheel message.
This will send a pitch-wheel message to any voices that are playing sounds on
the given midi channel.
This method will be called automatically according to the midi data passed into
renderNextBlock(), but may be called explicitly too.
@param midiChannel the midi channel, from 1 to 16 inclusive
@param wheelValue the wheel position, from 0 to 0x3fff, as returned by MidiMessage::getPitchWheelValue()
*/
virtual void handlePitchWheel (int midiChannel,
int wheelValue);
/** Sends a midi controller message.
This will send a midi controller message to any voices that are playing sounds on
the given midi channel.
This method will be called automatically according to the midi data passed into
renderNextBlock(), but may be called explicitly too.
@param midiChannel the midi channel, from 1 to 16 inclusive
@param controllerNumber the midi controller type, as returned by MidiMessage::getControllerNumber()
@param controllerValue the midi controller value, between 0 and 127, as returned by MidiMessage::getControllerValue()
*/
virtual void handleController (int midiChannel,
int controllerNumber,
int controllerValue);
virtual void handleSustainPedal (int midiChannel, bool isDown);
virtual void handleSostenutoPedal (int midiChannel, bool isDown);
virtual void handleSoftPedal (int midiChannel, bool isDown);
//==============================================================================
/** Tells the synthesiser what the sample rate is for the audio it's being used to
render.
This value is propagated to the voices so that they can use it to render the correct
pitches.
*/
void setCurrentPlaybackSampleRate (double sampleRate);
/** Creates the next block of audio output.
This will process the next numSamples of data from all the voices, and add that output
to the audio block supplied, starting from the offset specified. Note that the
data will be added to the current contents of the buffer, so you should clear it
before calling this method if necessary.
The midi events in the inputMidi buffer are parsed for note and controller events,
and these are used to trigger the voices. Note that the startSample offset applies
both to the audio output buffer and the midi input buffer, so any midi events
with timestamps outside the specified region will be ignored.
*/
void renderNextBlock (AudioSampleBuffer& outputAudio,
const MidiBuffer& inputMidi,
int startSample,
int numSamples);
protected:
//==============================================================================
/** This is used to control access to the rendering callback and the note trigger methods. */
CriticalSection lock;
OwnedArray <SynthesiserVoice> voices;
ReferenceCountedArray <SynthesiserSound> sounds;
/** The last pitch-wheel values for each midi channel. */
int lastPitchWheelValues [16];
/** Searches through the voices to find one that's not currently playing, and which
can play the given sound.
Returns nullptr if all voices are busy and stealing isn't enabled.
This can be overridden to implement custom voice-stealing algorithms.
*/
virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay,
const bool stealIfNoneAvailable) const;
/** Starts a specified voice playing a particular sound.
You'll probably never need to call this, it's used internally by noteOn(), but
may be needed by subclasses for custom behaviours.
*/
void startVoice (SynthesiserVoice* voice,
SynthesiserSound* sound,
int midiChannel,
int midiNoteNumber,
float velocity);
private:
//==============================================================================
double sampleRate;
uint32 lastNoteOnCounter;
bool shouldStealNotes;
BigInteger sustainPedalsDown;
void handleMidiEvent (const MidiMessage& m);
void stopVoice (SynthesiserVoice* voice, bool allowTailOff);
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
// Note the new parameters for this method.
virtual int findFreeVoice (const bool) const { return 0; }
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser)
};
#endif // __JUCE_SYNTHESISER_JUCEHEADER__

+ 170
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDBurner.h View File

@@ -0,0 +1,170 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOCDBURNER_JUCEHEADER__
#define __JUCE_AUDIOCDBURNER_JUCEHEADER__
#if JUCE_USE_CDBURNER || DOXYGEN
//==============================================================================
/**
*/
class AudioCDBurner : public ChangeBroadcaster
{
public:
//==============================================================================
/** Returns a list of available optical drives.
Use openDevice() to open one of the items from this list.
*/
static StringArray findAvailableDevices();
/** Tries to open one of the optical drives.
The deviceIndex is an index into the array returned by findAvailableDevices().
*/
static AudioCDBurner* openDevice (const int deviceIndex);
/** Destructor. */
~AudioCDBurner();
//==============================================================================
enum DiskState
{
unknown, /**< An error condition, if the device isn't responding. */
trayOpen, /**< The drive is currently open. Note that a slot-loading drive
may seem to be permanently open. */
noDisc, /**< The drive has no disk in it. */
writableDiskPresent, /**< The drive contains a writeable disk. */
readOnlyDiskPresent /**< The drive contains a read-only disk. */
};
/** Returns the current status of the device.
To get informed when the drive's status changes, attach a ChangeListener to
the AudioCDBurner.
*/
DiskState getDiskState() const;
/** Returns true if there's a writable disk in the drive. */
bool isDiskPresent() const;
/** Sends an eject signal to the drive.
The eject will happen asynchronously, so you can use getDiskState() and
waitUntilStateChange() to monitor its progress.
*/
bool openTray();
/** Blocks the current thread until the drive's state changes, or until the timeout expires.
@returns the device's new state
*/
DiskState waitUntilStateChange (int timeOutMilliseconds);
//==============================================================================
/** Returns the set of possible write speeds that the device can handle.
These are as a multiple of 'normal' speed, so e.g. '24x' returns 24, etc.
Note that if there's no media present in the drive, this value may be unavailable!
@see setWriteSpeed, getWriteSpeed
*/
Array<int> getAvailableWriteSpeeds() const;
//==============================================================================
/** Tries to enable or disable buffer underrun safety on devices that support it.
@returns true if it's now enabled. If the device doesn't support it, this
will always return false.
*/
bool setBufferUnderrunProtection (bool shouldBeEnabled);
//==============================================================================
/** Returns the number of free blocks on the disk.
There are 75 blocks per second, at 44100Hz.
*/
int getNumAvailableAudioBlocks() const;
/** Adds a track to be written.
The source passed-in here will be kept by this object, and it will
be used and deleted at some point in the future, either during the
burn() method or when this AudioCDBurner object is deleted. Your caller
method shouldn't keep a reference to it or use it again after passing
it in here.
*/
bool addAudioTrack (AudioSource* source, int numSamples);
//==============================================================================
/** Receives progress callbacks during a cd-burn operation.
@see AudioCDBurner::burn()
*/
class BurnProgressListener
{
public:
BurnProgressListener() noexcept {}
virtual ~BurnProgressListener() {}
/** Called at intervals to report on the progress of the AudioCDBurner.
To cancel the burn, return true from this method.
*/
virtual bool audioCDBurnProgress (float proportionComplete) = 0;
};
/** Runs the burn process.
This method will block until the operation is complete.
@param listener the object to receive callbacks about progress
@param ejectDiscAfterwards whether to eject the disk after the burn completes
@param performFakeBurnForTesting if true, no data will actually be written to the disk
@param writeSpeed one of the write speeds from getAvailableWriteSpeeds(), or
0 or less to mean the fastest speed.
*/
String burn (BurnProgressListener* listener,
bool ejectDiscAfterwards,
bool performFakeBurnForTesting,
int writeSpeed);
/** If a burn operation is currently in progress, this tells it to stop
as soon as possible.
It's also possible to stop the burn process by returning true from
BurnProgressListener::audioCDBurnProgress()
*/
void abortBurn();
private:
//==============================================================================
AudioCDBurner (const int deviceIndex);
class Pimpl;
friend class ScopedPointer<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioCDBurner)
};
#endif
#endif // __JUCE_AUDIOCDBURNER_JUCEHEADER__

+ 58
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.cpp View File

@@ -0,0 +1,58 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#if JUCE_USE_CDREADER
int AudioCDReader::getNumTracks() const
{
return trackStartSamples.size() - 1;
}
int AudioCDReader::getPositionOfTrackStart (int trackNum) const
{
return trackStartSamples [trackNum];
}
const Array<int>& AudioCDReader::getTrackOffsets() const
{
return trackStartSamples;
}
int AudioCDReader::getCDDBId()
{
int checksum = 0;
const int numTracks = getNumTracks();
for (int i = 0; i < numTracks; ++i)
for (int offset = (trackStartSamples.getUnchecked(i) + 88200) / 44100; offset > 0; offset /= 10)
checksum += offset % 10;
const int length = (trackStartSamples.getLast() - trackStartSamples.getFirst()) / 44100;
// CCLLLLTT: checksum, length, tracks
return ((checksum & 0xff) << 24) | (length << 8) | numTracks;
}
#endif

+ 175
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.h View File

@@ -0,0 +1,175 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOCDREADER_JUCEHEADER__
#define __JUCE_AUDIOCDREADER_JUCEHEADER__
#if JUCE_USE_CDREADER || DOXYGEN
//==============================================================================
/**
A type of AudioFormatReader that reads from an audio CD.
One of these can be used to read a CD as if it's one big audio stream. Use the
getPositionOfTrackStart() method to find where the individual tracks are
within the stream.
@see AudioFormatReader
*/
class JUCE_API AudioCDReader : public AudioFormatReader
{
public:
//==============================================================================
/** Returns a list of names of Audio CDs currently available for reading.
If there's a CD drive but no CD in it, this might return an empty list, or
possibly a device that can be opened but which has no tracks, depending
on the platform.
@see createReaderForCD
*/
static StringArray getAvailableCDNames();
/** Tries to create an AudioFormatReader that can read from an Audio CD.
@param index the index of one of the available CDs - use getAvailableCDNames()
to find out how many there are.
@returns a new AudioCDReader object, or nullptr if it couldn't be created. The
caller will be responsible for deleting the object returned.
*/
static AudioCDReader* createReaderForCD (const int index);
//==============================================================================
/** Destructor. */
~AudioCDReader();
/** Implementation of the AudioFormatReader method. */
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
int64 startSampleInFile, int numSamples);
/** Checks whether the CD has been removed from the drive. */
bool isCDStillPresent() const;
/** Returns the total number of tracks (audio + data). */
int getNumTracks() const;
/** Finds the sample offset of the start of a track.
@param trackNum the track number, where trackNum = 0 is the first track
and trackNum = getNumTracks() means the end of the CD.
*/
int getPositionOfTrackStart (int trackNum) const;
/** Returns true if a given track is an audio track.
@param trackNum the track number, where 0 is the first track.
*/
bool isTrackAudio (int trackNum) const;
/** Returns an array of sample offsets for the start of each track, followed by
the sample position of the end of the CD.
*/
const Array<int>& getTrackOffsets() const;
/** Refreshes the object's table of contents.
If the disc has been ejected and a different one put in since this
object was created, this will cause it to update its idea of how many tracks
there are, etc.
*/
void refreshTrackLengths();
/** Enables scanning for indexes within tracks.
@see getLastIndex
*/
void enableIndexScanning (bool enabled);
/** Returns the index number found during the last read() call.
Index scanning is turned off by default - turn it on with enableIndexScanning().
Then when the read() method is called, if it comes across an index within that
block, the index number is stored and returned by this method.
Some devices might not support indexes, of course.
(If you don't know what CD indexes are, it's unlikely you'll ever need them).
@see enableIndexScanning
*/
int getLastIndex() const;
/** Scans a track to find the position of any indexes within it.
@param trackNumber the track to look in, where 0 is the first track on the disc
@returns an array of sample positions of any index points found (not including
the index that marks the start of the track)
*/
Array<int> findIndexesInTrack (const int trackNumber);
/** Returns the CDDB id number for the CD.
It's not a great way of identifying a disc, but it's traditional.
*/
int getCDDBId();
/** Tries to eject the disk.
Ejecting the disk might not actually be possible, e.g. if some other process is using it.
*/
void ejectDisk();
//==============================================================================
enum
{
framesPerSecond = 75,
samplesPerFrame = 44100 / framesPerSecond
};
private:
//==============================================================================
Array<int> trackStartSamples;
#if JUCE_MAC
File volumeDir;
Array<File> tracks;
int currentReaderTrack;
ScopedPointer <AudioFormatReader> reader;
AudioCDReader (const File& volume);
#elif JUCE_WINDOWS
bool audioTracks [100];
void* handle;
MemoryBlock buffer;
bool indexingEnabled;
int lastIndex, firstFrameInBuffer, samplesInBuffer;
AudioCDReader (void* handle);
int getIndexAt (int samplePos);
#elif JUCE_LINUX
AudioCDReader();
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioCDReader)
};
#endif
#endif // __JUCE_AUDIOCDREADER_JUCEHEADER__

+ 953
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp View File

@@ -0,0 +1,953 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
AudioDeviceManager::AudioDeviceSetup::AudioDeviceSetup()
: sampleRate (0),
bufferSize (0),
useDefaultInputChannels (true),
useDefaultOutputChannels (true)
{
}
bool AudioDeviceManager::AudioDeviceSetup::operator== (const AudioDeviceManager::AudioDeviceSetup& other) const
{
return outputDeviceName == other.outputDeviceName
&& inputDeviceName == other.inputDeviceName
&& sampleRate == other.sampleRate
&& bufferSize == other.bufferSize
&& inputChannels == other.inputChannels
&& useDefaultInputChannels == other.useDefaultInputChannels
&& outputChannels == other.outputChannels
&& useDefaultOutputChannels == other.useDefaultOutputChannels;
}
//==============================================================================
class AudioDeviceManager::CallbackHandler : public AudioIODeviceCallback,
public MidiInputCallback,
public AudioIODeviceType::Listener
{
public:
CallbackHandler (AudioDeviceManager& adm) noexcept : owner (adm) {}
private:
void audioDeviceIOCallback (const float** ins, int numIns, float** outs, int numOuts, int numSamples)
{
owner.audioDeviceIOCallbackInt (ins, numIns, outs, numOuts, numSamples);
}
void audioDeviceAboutToStart (AudioIODevice* device)
{
owner.audioDeviceAboutToStartInt (device);
}
void audioDeviceStopped()
{
owner.audioDeviceStoppedInt();
}
void audioDeviceError (const String& message)
{
owner.audioDeviceErrorInt (message);
}
void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message)
{
owner.handleIncomingMidiMessageInt (source, message);
}
void audioDeviceListChanged()
{
owner.audioDeviceListChanged();
}
AudioDeviceManager& owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackHandler)
};
//==============================================================================
AudioDeviceManager::AudioDeviceManager()
: numInputChansNeeded (0),
numOutputChansNeeded (2),
listNeedsScanning (true),
useInputNames (false),
inputLevelMeasurementEnabledCount (0),
inputLevel (0),
tempBuffer (2, 2),
cpuUsageMs (0),
timeToCpuScale (0)
{
callbackHandler = new CallbackHandler (*this);
}
AudioDeviceManager::~AudioDeviceManager()
{
currentAudioDevice = nullptr;
defaultMidiOutput = nullptr;
}
//==============================================================================
void AudioDeviceManager::createDeviceTypesIfNeeded()
{
if (availableDeviceTypes.size() == 0)
{
createAudioDeviceTypes (availableDeviceTypes);
while (lastDeviceTypeConfigs.size() < availableDeviceTypes.size())
lastDeviceTypeConfigs.add (new AudioDeviceSetup());
if (availableDeviceTypes.size() > 0)
currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
for (int i = 0; i < availableDeviceTypes.size(); ++i)
availableDeviceTypes.getUnchecked(i)->addListener (callbackHandler);
}
}
const OwnedArray <AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
{
scanDevicesIfNeeded();
return availableDeviceTypes;
}
void AudioDeviceManager::audioDeviceListChanged()
{
sendChangeMessage();
}
//==============================================================================
static void addIfNotNull (OwnedArray <AudioIODeviceType>& list, AudioIODeviceType* const device)
{
if (device != nullptr)
list.add (device);
}
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& list)
{
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ASIO());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_CoreAudio());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_iOSAudio());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ALSA());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_JACK());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_OpenSLES());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Android());
}
void AudioDeviceManager::addAudioDeviceType (AudioIODeviceType* newDeviceType)
{
jassert (newDeviceType != nullptr);
availableDeviceTypes.add (newDeviceType);
}
//==============================================================================
String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
const int numOutputChannelsNeeded,
const XmlElement* const e,
const bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName,
const AudioDeviceSetup* preferredSetupOptions)
{
scanDevicesIfNeeded();
numInputChansNeeded = numInputChannelsNeeded;
numOutputChansNeeded = numOutputChannelsNeeded;
if (e != nullptr && e->hasTagName ("DEVICESETUP"))
{
lastExplicitSettings = new XmlElement (*e);
String error;
AudioDeviceSetup setup;
if (preferredSetupOptions != nullptr)
setup = *preferredSetupOptions;
if (e->getStringAttribute ("audioDeviceName").isNotEmpty())
{
setup.inputDeviceName = setup.outputDeviceName
= e->getStringAttribute ("audioDeviceName");
}
else
{
setup.inputDeviceName = e->getStringAttribute ("audioInputDeviceName");
setup.outputDeviceName = e->getStringAttribute ("audioOutputDeviceName");
}
currentDeviceType = e->getStringAttribute ("deviceType");
if (findType (currentDeviceType) == nullptr)
{
if (AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName))
currentDeviceType = type->getTypeName();
else if (availableDeviceTypes.size() > 0)
currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
}
setup.bufferSize = e->getIntAttribute ("audioDeviceBufferSize");
setup.sampleRate = e->getDoubleAttribute ("audioDeviceRate");
setup.inputChannels .parseString (e->getStringAttribute ("audioDeviceInChans", "11"), 2);
setup.outputChannels.parseString (e->getStringAttribute ("audioDeviceOutChans", "11"), 2);
setup.useDefaultInputChannels = ! e->hasAttribute ("audioDeviceInChans");
setup.useDefaultOutputChannels = ! e->hasAttribute ("audioDeviceOutChans");
error = setAudioDeviceSetup (setup, true);
midiInsFromXml.clear();
forEachXmlChildElementWithTagName (*e, c, "MIDIINPUT")
midiInsFromXml.add (c->getStringAttribute ("name"));
const StringArray allMidiIns (MidiInput::getDevices());
for (int i = allMidiIns.size(); --i >= 0;)
setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
error = initialise (numInputChannelsNeeded, numOutputChannelsNeeded, 0,
false, preferredDefaultDeviceName);
setDefaultMidiOutput (e->getStringAttribute ("defaultMidiOutput"));
return error;
}
else
{
AudioDeviceSetup setup;
if (preferredSetupOptions != nullptr)
{
setup = *preferredSetupOptions;
}
else if (preferredDefaultDeviceName.isNotEmpty())
{
for (int j = availableDeviceTypes.size(); --j >= 0;)
{
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j);
const StringArray outs (type->getDeviceNames (false));
for (int i = 0; i < outs.size(); ++i)
{
if (outs[i].matchesWildcard (preferredDefaultDeviceName, true))
{
setup.outputDeviceName = outs[i];
break;
}
}
const StringArray ins (type->getDeviceNames (true));
for (int i = 0; i < ins.size(); ++i)
{
if (ins[i].matchesWildcard (preferredDefaultDeviceName, true))
{
setup.inputDeviceName = ins[i];
break;
}
}
}
}
insertDefaultDeviceNames (setup);
return setAudioDeviceSetup (setup, false);
}
}
void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
{
if (AudioIODeviceType* type = getCurrentDeviceTypeObject())
{
if (setup.outputDeviceName.isEmpty())
setup.outputDeviceName = type->getDeviceNames (false) [type->getDefaultDeviceIndex (false)];
if (setup.inputDeviceName.isEmpty())
setup.inputDeviceName = type->getDeviceNames (true) [type->getDefaultDeviceIndex (true)];
}
}
XmlElement* AudioDeviceManager::createStateXml() const
{
return lastExplicitSettings.createCopy();
}
//==============================================================================
void AudioDeviceManager::scanDevicesIfNeeded()
{
if (listNeedsScanning)
{
listNeedsScanning = false;
createDeviceTypesIfNeeded();
for (int i = availableDeviceTypes.size(); --i >= 0;)
availableDeviceTypes.getUnchecked(i)->scanForDevices();
}
}
AudioIODeviceType* AudioDeviceManager::findType (const String& typeName)
{
scanDevicesIfNeeded();
for (int i = availableDeviceTypes.size(); --i >= 0;)
if (availableDeviceTypes.getUnchecked(i)->getTypeName() == typeName)
return availableDeviceTypes.getUnchecked(i);
return nullptr;
}
AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const String& outputName)
{
scanDevicesIfNeeded();
for (int i = availableDeviceTypes.size(); --i >= 0;)
{
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(i);
if ((inputName.isNotEmpty() && type->getDeviceNames (true).contains (inputName, true))
|| (outputName.isNotEmpty() && type->getDeviceNames (false).contains (outputName, true)))
{
return type;
}
}
return nullptr;
}
void AudioDeviceManager::getAudioDeviceSetup (AudioDeviceSetup& setup)
{
setup = currentSetup;
}
void AudioDeviceManager::deleteCurrentDevice()
{
currentAudioDevice = nullptr;
currentSetup.inputDeviceName = String::empty;
currentSetup.outputDeviceName = String::empty;
}
void AudioDeviceManager::setCurrentAudioDeviceType (const String& type,
const bool treatAsChosenDevice)
{
for (int i = 0; i < availableDeviceTypes.size(); ++i)
{
if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type
&& currentDeviceType != type)
{
currentDeviceType = type;
AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i));
insertDefaultDeviceNames (s);
setAudioDeviceSetup (s, treatAsChosenDevice);
sendChangeMessage();
break;
}
}
}
AudioIODeviceType* AudioDeviceManager::getCurrentDeviceTypeObject() const
{
for (int i = 0; i < availableDeviceTypes.size(); ++i)
if (availableDeviceTypes[i]->getTypeName() == currentDeviceType)
return availableDeviceTypes[i];
return availableDeviceTypes[0];
}
String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup,
const bool treatAsChosenDevice)
{
jassert (&newSetup != &currentSetup); // this will have no effect
if (newSetup == currentSetup && currentAudioDevice != nullptr)
return String::empty;
if (! (newSetup == currentSetup))
sendChangeMessage();
stopDevice();
const String newInputDeviceName (numInputChansNeeded == 0 ? String::empty : newSetup.inputDeviceName);
const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName);
String error;
AudioIODeviceType* type = getCurrentDeviceTypeObject();
if (type == nullptr || (newInputDeviceName.isEmpty() && newOutputDeviceName.isEmpty()))
{
deleteCurrentDevice();
if (treatAsChosenDevice)
updateXml();
return String::empty;
}
if (currentSetup.inputDeviceName != newInputDeviceName
|| currentSetup.outputDeviceName != newOutputDeviceName
|| currentAudioDevice == nullptr)
{
deleteCurrentDevice();
scanDevicesIfNeeded();
if (newOutputDeviceName.isNotEmpty()
&& ! type->getDeviceNames (false).contains (newOutputDeviceName))
{
return "No such device: " + newOutputDeviceName;
}
if (newInputDeviceName.isNotEmpty()
&& ! type->getDeviceNames (true).contains (newInputDeviceName))
{
return "No such device: " + newInputDeviceName;
}
currentAudioDevice = type->createDevice (newOutputDeviceName, newInputDeviceName);
if (currentAudioDevice == nullptr)
error = "Can't open the audio device!\n\nThis may be because another application is currently using the same device - if so, you should close any other applications and try again!";
else
error = currentAudioDevice->getLastError();
if (error.isNotEmpty())
{
deleteCurrentDevice();
return error;
}
if (newSetup.useDefaultInputChannels)
{
inputChannels.clear();
inputChannels.setRange (0, numInputChansNeeded, true);
}
if (newSetup.useDefaultOutputChannels)
{
outputChannels.clear();
outputChannels.setRange (0, numOutputChansNeeded, true);
}
if (newInputDeviceName.isEmpty()) inputChannels.clear();
if (newOutputDeviceName.isEmpty()) outputChannels.clear();
}
if (! newSetup.useDefaultInputChannels) inputChannels = newSetup.inputChannels;
if (! newSetup.useDefaultOutputChannels) outputChannels = newSetup.outputChannels;
currentSetup = newSetup;
currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate);
currentSetup.bufferSize = chooseBestBufferSize (newSetup.bufferSize);
error = currentAudioDevice->open (inputChannels,
outputChannels,
currentSetup.sampleRate,
currentSetup.bufferSize);
if (error.isEmpty())
{
currentDeviceType = currentAudioDevice->getTypeName();
currentAudioDevice->start (callbackHandler);
currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
for (int i = 0; i < availableDeviceTypes.size(); ++i)
if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType)
*(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup;
if (treatAsChosenDevice)
updateXml();
}
else
{
deleteCurrentDevice();
}
return error;
}
double AudioDeviceManager::chooseBestSampleRate (double rate) const
{
jassert (currentAudioDevice != nullptr);
if (rate > 0)
for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
if (currentAudioDevice->getSampleRate (i) == rate)
return rate;
double lowestAbove44 = 0.0;
for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
{
const double sr = currentAudioDevice->getSampleRate (i);
if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44))
lowestAbove44 = sr;
}
if (lowestAbove44 > 0.0)
return lowestAbove44;
return currentAudioDevice->getSampleRate (0);
}
int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const
{
jassert (currentAudioDevice != nullptr);
if (bufferSize > 0)
for (int i = currentAudioDevice->getNumBufferSizesAvailable(); --i >= 0;)
if (currentAudioDevice->getBufferSizeSamples(i) == bufferSize)
return bufferSize;
return currentAudioDevice->getDefaultBufferSize();
}
void AudioDeviceManager::stopDevice()
{
if (currentAudioDevice != nullptr)
currentAudioDevice->stop();
testSound = nullptr;
}
void AudioDeviceManager::closeAudioDevice()
{
stopDevice();
currentAudioDevice = nullptr;
}
void AudioDeviceManager::restartLastAudioDevice()
{
if (currentAudioDevice == nullptr)
{
if (currentSetup.inputDeviceName.isEmpty()
&& currentSetup.outputDeviceName.isEmpty())
{
// This method will only reload the last device that was running
// before closeAudioDevice() was called - you need to actually open
// one first, with setAudioDevice().
jassertfalse;
return;
}
AudioDeviceSetup s (currentSetup);
setAudioDeviceSetup (s, false);
}
}
void AudioDeviceManager::updateXml()
{
lastExplicitSettings = new XmlElement ("DEVICESETUP");
lastExplicitSettings->setAttribute ("deviceType", currentDeviceType);
lastExplicitSettings->setAttribute ("audioOutputDeviceName", currentSetup.outputDeviceName);
lastExplicitSettings->setAttribute ("audioInputDeviceName", currentSetup.inputDeviceName);
if (currentAudioDevice != nullptr)
{
lastExplicitSettings->setAttribute ("audioDeviceRate", currentAudioDevice->getCurrentSampleRate());
if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
lastExplicitSettings->setAttribute ("audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());
if (! currentSetup.useDefaultInputChannels)
lastExplicitSettings->setAttribute ("audioDeviceInChans", currentSetup.inputChannels.toString (2));
if (! currentSetup.useDefaultOutputChannels)
lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2));
}
for (int i = 0; i < enabledMidiInputs.size(); ++i)
lastExplicitSettings->createNewChildElement ("MIDIINPUT")
->setAttribute ("name", enabledMidiInputs[i]->getName());
if (midiInsFromXml.size() > 0)
{
// Add any midi devices that have been enabled before, but which aren't currently
// open because the device has been disconnected.
const StringArray availableMidiDevices (MidiInput::getDevices());
for (int i = 0; i < midiInsFromXml.size(); ++i)
{
if (! availableMidiDevices.contains (midiInsFromXml[i], true))
{
lastExplicitSettings->createNewChildElement ("MIDIINPUT")
->setAttribute ("name", midiInsFromXml[i]);
}
}
}
if (defaultMidiOutputName.isNotEmpty())
lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputName);
}
//==============================================================================
void AudioDeviceManager::addAudioCallback (AudioIODeviceCallback* newCallback)
{
{
const ScopedLock sl (audioCallbackLock);
if (callbacks.contains (newCallback))
return;
}
if (currentAudioDevice != nullptr && newCallback != nullptr)
newCallback->audioDeviceAboutToStart (currentAudioDevice);
const ScopedLock sl (audioCallbackLock);
callbacks.add (newCallback);
}
void AudioDeviceManager::removeAudioCallback (AudioIODeviceCallback* callbackToRemove)
{
if (callbackToRemove != nullptr)
{
bool needsDeinitialising = currentAudioDevice != nullptr;
{
const ScopedLock sl (audioCallbackLock);
needsDeinitialising = needsDeinitialising && callbacks.contains (callbackToRemove);
callbacks.removeFirstMatchingValue (callbackToRemove);
}
if (needsDeinitialising)
callbackToRemove->audioDeviceStopped();
}
}
void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,
int numInputChannels,
float** outputChannelData,
int numOutputChannels,
int numSamples)
{
const ScopedLock sl (audioCallbackLock);
if (inputLevelMeasurementEnabledCount > 0 && numInputChannels > 0)
{
for (int j = 0; j < numSamples; ++j)
{
float s = 0;
for (int i = 0; i < numInputChannels; ++i)
s += std::abs (inputChannelData[i][j]);
s /= numInputChannels;
const double decayFactor = 0.99992;
if (s > inputLevel)
inputLevel = s;
else if (inputLevel > 0.001f)
inputLevel *= decayFactor;
else
inputLevel = 0;
}
}
else
{
inputLevel = 0;
}
if (callbacks.size() > 0)
{
const double callbackStartTime = Time::getMillisecondCounterHiRes();
tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true);
callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels,
outputChannelData, numOutputChannels, numSamples);
float** const tempChans = tempBuffer.getArrayOfChannels();
for (int i = callbacks.size(); --i > 0;)
{
callbacks.getUnchecked(i)->audioDeviceIOCallback (inputChannelData, numInputChannels,
tempChans, numOutputChannels, numSamples);
for (int chan = 0; chan < numOutputChannels; ++chan)
{
if (const float* const src = tempChans [chan])
if (float* const dst = outputChannelData [chan])
for (int j = 0; j < numSamples; ++j)
dst[j] += src[j];
}
}
const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime;
const double filterAmount = 0.2;
cpuUsageMs += filterAmount * (msTaken - cpuUsageMs);
}
else
{
for (int i = 0; i < numOutputChannels; ++i)
zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples);
}
if (testSound != nullptr)
{
const int numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
const float* const src = testSound->getSampleData (0, testSoundPosition);
for (int i = 0; i < numOutputChannels; ++i)
for (int j = 0; j < numSamps; ++j)
outputChannelData [i][j] += src[j];
testSoundPosition += numSamps;
if (testSoundPosition >= testSound->getNumSamples())
testSound = nullptr;
}
}
void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)
{
cpuUsageMs = 0;
const double sampleRate = device->getCurrentSampleRate();
const int blockSize = device->getCurrentBufferSizeSamples();
if (sampleRate > 0.0 && blockSize > 0)
{
const double msPerBlock = 1000.0 * blockSize / sampleRate;
timeToCpuScale = (msPerBlock > 0.0) ? (1.0 / msPerBlock) : 0.0;
}
{
const ScopedLock sl (audioCallbackLock);
for (int i = callbacks.size(); --i >= 0;)
callbacks.getUnchecked(i)->audioDeviceAboutToStart (device);
}
sendChangeMessage();
}
void AudioDeviceManager::audioDeviceStoppedInt()
{
cpuUsageMs = 0;
timeToCpuScale = 0;
sendChangeMessage();
const ScopedLock sl (audioCallbackLock);
for (int i = callbacks.size(); --i >= 0;)
callbacks.getUnchecked(i)->audioDeviceStopped();
}
void AudioDeviceManager::audioDeviceErrorInt (const String& message)
{
const ScopedLock sl (audioCallbackLock);
for (int i = callbacks.size(); --i >= 0;)
callbacks.getUnchecked(i)->audioDeviceError (message);
}
double AudioDeviceManager::getCpuUsage() const
{
return jlimit (0.0, 1.0, timeToCpuScale * cpuUsageMs);
}
//==============================================================================
void AudioDeviceManager::setMidiInputEnabled (const String& name, const bool enabled)
{
if (enabled != isMidiInputEnabled (name))
{
if (enabled)
{
const int index = MidiInput::getDevices().indexOf (name);
if (index >= 0)
{
if (MidiInput* const midiIn = MidiInput::openDevice (index, callbackHandler))
{
enabledMidiInputs.add (midiIn);
midiIn->start();
}
}
}
else
{
for (int i = enabledMidiInputs.size(); --i >= 0;)
if (enabledMidiInputs[i]->getName() == name)
enabledMidiInputs.remove (i);
}
updateXml();
sendChangeMessage();
}
}
bool AudioDeviceManager::isMidiInputEnabled (const String& name) const
{
for (int i = enabledMidiInputs.size(); --i >= 0;)
if (enabledMidiInputs[i]->getName() == name)
return true;
return false;
}
void AudioDeviceManager::addMidiInputCallback (const String& name, MidiInputCallback* callbackToAdd)
{
removeMidiInputCallback (name, callbackToAdd);
if (name.isEmpty() || isMidiInputEnabled (name))
{
const ScopedLock sl (midiCallbackLock);
midiCallbacks.add (callbackToAdd);
midiCallbackDevices.add (name);
}
}
void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callbackToRemove)
{
for (int i = midiCallbacks.size(); --i >= 0;)
{
if (midiCallbackDevices[i] == name && midiCallbacks.getUnchecked(i) == callbackToRemove)
{
const ScopedLock sl (midiCallbackLock);
midiCallbacks.remove (i);
midiCallbackDevices.remove (i);
}
}
}
void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source, const MidiMessage& message)
{
if (! message.isActiveSense())
{
const bool isDefaultSource = (source == nullptr || source == enabledMidiInputs.getFirst());
const ScopedLock sl (midiCallbackLock);
for (int i = midiCallbackDevices.size(); --i >= 0;)
{
const String name (midiCallbackDevices[i]);
if ((isDefaultSource && name.isEmpty()) || (name.isNotEmpty() && name == source->getName()))
midiCallbacks.getUnchecked(i)->handleIncomingMidiMessage (source, message);
}
}
}
//==============================================================================
void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
{
if (defaultMidiOutputName != deviceName)
{
Array <AudioIODeviceCallback*> oldCallbacks;
{
const ScopedLock sl (audioCallbackLock);
oldCallbacks = callbacks;
callbacks.clear();
}
if (currentAudioDevice != nullptr)
for (int i = oldCallbacks.size(); --i >= 0;)
oldCallbacks.getUnchecked(i)->audioDeviceStopped();
defaultMidiOutput = nullptr;
defaultMidiOutputName = deviceName;
if (deviceName.isNotEmpty())
defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName));
if (currentAudioDevice != nullptr)
for (int i = oldCallbacks.size(); --i >= 0;)
oldCallbacks.getUnchecked(i)->audioDeviceAboutToStart (currentAudioDevice);
{
const ScopedLock sl (audioCallbackLock);
callbacks = oldCallbacks;
}
updateXml();
sendChangeMessage();
}
}
//==============================================================================
void AudioDeviceManager::playTestSound()
{
{ // cunningly nested to swap, unlock and delete in that order.
ScopedPointer <AudioSampleBuffer> oldSound;
{
const ScopedLock sl (audioCallbackLock);
oldSound = testSound;
}
}
testSoundPosition = 0;
if (currentAudioDevice != nullptr)
{
const double sampleRate = currentAudioDevice->getCurrentSampleRate();
const int soundLength = (int) sampleRate;
AudioSampleBuffer* const newSound = new AudioSampleBuffer (1, soundLength);
float* samples = newSound->getSampleData (0);
const double frequency = 440.0;
const float amplitude = 0.5f;
const double phasePerSample = double_Pi * 2.0 / (sampleRate / frequency);
for (int i = 0; i < soundLength; ++i)
samples[i] = amplitude * (float) std::sin (i * phasePerSample);
newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
const ScopedLock sl (audioCallbackLock);
testSound = newSound;
}
}
void AudioDeviceManager::enableInputLevelMeasurement (const bool enableMeasurement)
{
const ScopedLock sl (audioCallbackLock);
if (enableMeasurement)
++inputLevelMeasurementEnabledCount;
else
--inputLevelMeasurementEnabledCount;
inputLevel = 0;
}
double AudioDeviceManager::getCurrentInputLevel() const
{
jassert (inputLevelMeasurementEnabledCount > 0); // you need to call enableInputLevelMeasurement() before using this!
return inputLevel;
}

+ 512
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h View File

@@ -0,0 +1,512 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIODEVICEMANAGER_JUCEHEADER__
#define __JUCE_AUDIODEVICEMANAGER_JUCEHEADER__
#include "juce_AudioIODeviceType.h"
#include "../midi_io/juce_MidiInput.h"
#include "../midi_io/juce_MidiOutput.h"
//==============================================================================
/**
Manages the state of some audio and midi i/o devices.
This class keeps tracks of a currently-selected audio device, through
with which it continuously streams data from an audio callback, as well as
one or more midi inputs.
The idea is that your application will create one global instance of this object,
and let it take care of creating and deleting specific types of audio devices
internally. So when the device is changed, your callbacks will just keep running
without having to worry about this.
The manager can save and reload all of its device settings as XML, which
makes it very easy for you to save and reload the audio setup of your
application.
And to make it easy to let the user change its settings, there's a component
to do just that - the AudioDeviceSelectorComponent class, which contains a set of
device selection/sample-rate/latency controls.
To use an AudioDeviceManager, create one, and use initialise() to set it up. Then
call addAudioCallback() to register your audio callback with it, and use that to process
your audio data.
The manager also acts as a handy hub for incoming midi messages, allowing a
listener to register for messages from either a specific midi device, or from whatever
the current default midi input device is. The listener then doesn't have to worry about
re-registering with different midi devices if they are changed or deleted.
And yet another neat trick is that amount of CPU time being used is measured and
available with the getCpuUsage() method.
The AudioDeviceManager is a ChangeBroadcaster, and will send a change message to
listeners whenever one of its settings is changed.
@see AudioDeviceSelectorComponent, AudioIODevice, AudioIODeviceType
*/
class JUCE_API AudioDeviceManager : public ChangeBroadcaster
{
public:
//==============================================================================
/** Creates a default AudioDeviceManager.
Initially no audio device will be selected. You should call the initialise() method
and register an audio callback with setAudioCallback() before it'll be able to
actually make any noise.
*/
AudioDeviceManager();
/** Destructor. */
~AudioDeviceManager();
//==============================================================================
/**
This structure holds a set of properties describing the current audio setup.
An AudioDeviceManager uses this class to save/load its current settings, and to
specify your preferred options when opening a device.
@see AudioDeviceManager::setAudioDeviceSetup(), AudioDeviceManager::initialise()
*/
struct JUCE_API AudioDeviceSetup
{
/** Creates an AudioDeviceSetup object.
The default constructor sets all the member variables to indicate default values.
You can then fill-in any values you want to before passing the object to
AudioDeviceManager::initialise().
*/
AudioDeviceSetup();
bool operator== (const AudioDeviceSetup& other) const;
/** The name of the audio device used for output.
The name has to be one of the ones listed by the AudioDeviceManager's currently
selected device type.
This may be the same as the input device.
An empty string indicates the default device.
*/
String outputDeviceName;
/** The name of the audio device used for input.
This may be the same as the output device.
An empty string indicates the default device.
*/
String inputDeviceName;
/** The current sample rate.
This rate is used for both the input and output devices.
A value of 0 indicates that you don't care what rate is used, and the
device will choose a sensible rate for you.
*/
double sampleRate;
/** The buffer size, in samples.
This buffer size is used for both the input and output devices.
A value of 0 indicates the default buffer size.
*/
int bufferSize;
/** The set of active input channels.
The bits that are set in this array indicate the channels of the
input device that are active.
If useDefaultInputChannels is true, this value is ignored.
*/
BigInteger inputChannels;
/** If this is true, it indicates that the inputChannels array
should be ignored, and instead, the device's default channels
should be used.
*/
bool useDefaultInputChannels;
/** The set of active output channels.
The bits that are set in this array indicate the channels of the
input device that are active.
If useDefaultOutputChannels is true, this value is ignored.
*/
BigInteger outputChannels;
/** If this is true, it indicates that the outputChannels array
should be ignored, and instead, the device's default channels
should be used.
*/
bool useDefaultOutputChannels;
};
//==============================================================================
/** Opens a set of audio devices ready for use.
This will attempt to open either a default audio device, or one that was
previously saved as XML.
@param numInputChannelsNeeded a minimum number of input channels needed
by your app.
@param numOutputChannelsNeeded a minimum number of output channels to open
@param savedState either a previously-saved state that was produced
by createStateXml(), or nullptr if you want the manager
to choose the best device to open.
@param selectDefaultDeviceOnFailure if true, then if the device specified in the XML
fails to open, then a default device will be used
instead. If false, then on failure, no device is
opened.
@param preferredDefaultDeviceName if this is not empty, and there's a device with this
name, then that will be used as the default device
(assuming that there wasn't one specified in the XML).
The string can actually be a simple wildcard, containing "*"
and "?" characters
@param preferredSetupOptions if this is non-null, the structure will be used as the
set of preferred settings when opening the device. If you
use this parameter, the preferredDefaultDeviceName
field will be ignored
@returns an error message if anything went wrong, or an empty string if it worked ok.
*/
String initialise (int numInputChannelsNeeded,
int numOutputChannelsNeeded,
const XmlElement* savedState,
bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName = String::empty,
const AudioDeviceSetup* preferredSetupOptions = 0);
/** Returns some XML representing the current state of the manager.
This stores the current device, its samplerate, block size, etc, and
can be restored later with initialise().
Note that this can return a null pointer if no settings have been explicitly changed
(i.e. if the device manager has just been left in its default state).
*/
XmlElement* createStateXml() const;
//==============================================================================
/** Returns the current device properties that are in use.
@see setAudioDeviceSetup
*/
void getAudioDeviceSetup (AudioDeviceSetup& setup);
/** Changes the current device or its settings.
If you want to change a device property, like the current sample rate or
block size, you can call getAudioDeviceSetup() to retrieve the current
settings, then tweak the appropriate fields in the AudioDeviceSetup structure,
and pass it back into this method to apply the new settings.
@param newSetup the settings that you'd like to use
@param treatAsChosenDevice if this is true and if the device opens correctly, these new
settings will be taken as having been explicitly chosen by the
user, and the next time createStateXml() is called, these settings
will be returned. If it's false, then the device is treated as a
temporary or default device, and a call to createStateXml() will
return either the last settings that were made with treatAsChosenDevice
as true, or the last XML settings that were passed into initialise().
@returns an error message if anything went wrong, or an empty string if it worked ok.
@see getAudioDeviceSetup
*/
String setAudioDeviceSetup (const AudioDeviceSetup& newSetup,
bool treatAsChosenDevice);
/** Returns the currently-active audio device. */
AudioIODevice* getCurrentAudioDevice() const noexcept { return currentAudioDevice; }
/** Returns the type of audio device currently in use.
@see setCurrentAudioDeviceType
*/
String getCurrentAudioDeviceType() const { return currentDeviceType; }
/** Returns the currently active audio device type object.
Don't keep a copy of this pointer - it's owned by the device manager and could
change at any time.
*/
AudioIODeviceType* getCurrentDeviceTypeObject() const;
/** Changes the class of audio device being used.
This switches between, e.g. ASIO and DirectSound. On the Mac you probably won't ever call
this because there's only one type: CoreAudio.
For a list of types, see getAvailableDeviceTypes().
*/
void setCurrentAudioDeviceType (const String& type,
bool treatAsChosenDevice);
/** Closes the currently-open device.
You can call restartLastAudioDevice() later to reopen it in the same state
that it was just in.
*/
void closeAudioDevice();
/** Tries to reload the last audio device that was running.
Note that this only reloads the last device that was running before
closeAudioDevice() was called - it doesn't reload any kind of saved-state,
and can only be called after a device has been opened with SetAudioDevice().
If a device is already open, this call will do nothing.
*/
void restartLastAudioDevice();
//==============================================================================
/** Registers an audio callback to be used.
The manager will redirect callbacks from whatever audio device is currently
in use to all registered callback objects. If more than one callback is
active, they will all be given the same input data, and their outputs will
be summed.
If necessary, this method will invoke audioDeviceAboutToStart() on the callback
object before returning.
To remove a callback, use removeAudioCallback().
*/
void addAudioCallback (AudioIODeviceCallback* newCallback);
/** Deregisters a previously added callback.
If necessary, this method will invoke audioDeviceStopped() on the callback
object before returning.
@see addAudioCallback
*/
void removeAudioCallback (AudioIODeviceCallback* callback);
//==============================================================================
/** Returns the average proportion of available CPU being spent inside the audio callbacks.
Returns a value between 0 and 1.0
*/
double getCpuUsage() const;
//==============================================================================
/** Enables or disables a midi input device.
The list of devices can be obtained with the MidiInput::getDevices() method.
Any incoming messages from enabled input devices will be forwarded on to all the
listeners that have been registered with the addMidiInputCallback() method. They
can either register for messages from a particular device, or from just the
"default" midi input.
Routing the midi input via an AudioDeviceManager means that when a listener
registers for the default midi input, this default device can be changed by the
manager without the listeners having to know about it or re-register.
It also means that a listener can stay registered for a midi input that is disabled
or not present, so that when the input is re-enabled, the listener will start
receiving messages again.
@see addMidiInputCallback, isMidiInputEnabled
*/
void setMidiInputEnabled (const String& midiInputDeviceName, bool enabled);
/** Returns true if a given midi input device is being used.
@see setMidiInputEnabled
*/
bool isMidiInputEnabled (const String& midiInputDeviceName) const;
/** Registers a listener for callbacks when midi events arrive from a midi input.
The device name can be empty to indicate that it wants events from whatever the
current "default" device is. Or it can be the name of one of the midi input devices
(see MidiInput::getDevices() for the names).
Only devices which are enabled (see the setMidiInputEnabled() method) will have their
events forwarded on to listeners.
*/
void addMidiInputCallback (const String& midiInputDeviceName,
MidiInputCallback* callback);
/** Removes a listener that was previously registered with addMidiInputCallback().
*/
void removeMidiInputCallback (const String& midiInputDeviceName,
MidiInputCallback* callback);
//==============================================================================
/** Sets a midi output device to use as the default.
The list of devices can be obtained with the MidiOutput::getDevices() method.
The specified device will be opened automatically and can be retrieved with the
getDefaultMidiOutput() method.
Pass in an empty string to deselect all devices. For the default device, you
can use MidiOutput::getDevices() [MidiOutput::getDefaultDeviceIndex()].
@see getDefaultMidiOutput, getDefaultMidiOutputName
*/
void setDefaultMidiOutput (const String& deviceName);
/** Returns the name of the default midi output.
@see setDefaultMidiOutput, getDefaultMidiOutput
*/
String getDefaultMidiOutputName() const { return defaultMidiOutputName; }
/** Returns the current default midi output device.
If no device has been selected, or the device can't be opened, this will
return 0.
@see getDefaultMidiOutputName
*/
MidiOutput* getDefaultMidiOutput() const noexcept { return defaultMidiOutput; }
/** Returns a list of the types of device supported.
*/
const OwnedArray <AudioIODeviceType>& getAvailableDeviceTypes();
//==============================================================================
/** Creates a list of available types.
This will add a set of new AudioIODeviceType objects to the specified list, to
represent each available types of device.
You can override this if your app needs to do something specific, like avoid
using DirectSound devices, etc.
*/
virtual void createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& types);
/** Adds a new device type to the list of types.
The manager will take ownership of the object that is passed-in.
*/
void addAudioDeviceType (AudioIODeviceType* newDeviceType);
//==============================================================================
/** Plays a beep through the current audio device.
This is here to allow the audio setup UI panels to easily include a "test"
button so that the user can check where the audio is coming from.
*/
void playTestSound();
/** Turns on level-measuring.
When enabled, the device manager will measure the peak input level
across all channels, and you can get this level by calling getCurrentInputLevel().
This is mainly intended for audio setup UI panels to use to create a mic
level display, so that the user can check that they've selected the right
device.
A simple filter is used to make the level decay smoothly, but this is
only intended for giving rough feedback, and not for any kind of accurate
measurement.
*/
void enableInputLevelMeasurement (bool enableMeasurement);
/** Returns the current input level.
To use this, you must first enable it by calling enableInputLevelMeasurement().
See enableInputLevelMeasurement() for more info.
*/
double getCurrentInputLevel() const;
/** Returns the a lock that can be used to synchronise access to the audio callback.
Obviously while this is locked, you're blocking the audio thread from running, so
it must only be used for very brief periods when absolutely necessary.
*/
CriticalSection& getAudioCallbackLock() noexcept { return audioCallbackLock; }
/** Returns the a lock that can be used to synchronise access to the midi callback.
Obviously while this is locked, you're blocking the midi system from running, so
it must only be used for very brief periods when absolutely necessary.
*/
CriticalSection& getMidiCallbackLock() noexcept { return midiCallbackLock; }
private:
//==============================================================================
OwnedArray <AudioIODeviceType> availableDeviceTypes;
OwnedArray <AudioDeviceSetup> lastDeviceTypeConfigs;
AudioDeviceSetup currentSetup;
ScopedPointer <AudioIODevice> currentAudioDevice;
Array <AudioIODeviceCallback*> callbacks;
int numInputChansNeeded, numOutputChansNeeded;
String currentDeviceType;
BigInteger inputChannels, outputChannels;
ScopedPointer <XmlElement> lastExplicitSettings;
mutable bool listNeedsScanning;
bool useInputNames;
int inputLevelMeasurementEnabledCount;
double inputLevel;
ScopedPointer <AudioSampleBuffer> testSound;
int testSoundPosition;
AudioSampleBuffer tempBuffer;
StringArray midiInsFromXml;
OwnedArray <MidiInput> enabledMidiInputs;
Array <MidiInputCallback*> midiCallbacks;
StringArray midiCallbackDevices;
String defaultMidiOutputName;
ScopedPointer <MidiOutput> defaultMidiOutput;
CriticalSection audioCallbackLock, midiCallbackLock;
double cpuUsageMs, timeToCpuScale;
//==============================================================================
class CallbackHandler;
friend class CallbackHandler;
friend class ScopedPointer<CallbackHandler>;
ScopedPointer<CallbackHandler> callbackHandler;
void audioDeviceIOCallbackInt (const float** inputChannelData, int totalNumInputChannels,
float** outputChannelData, int totalNumOutputChannels, int numSamples);
void audioDeviceAboutToStartInt (AudioIODevice*);
void audioDeviceStoppedInt();
void audioDeviceErrorInt (const String&);
void handleIncomingMidiMessageInt (MidiInput*, const MidiMessage&);
void audioDeviceListChanged();
String restartDevice (int blockSizeToUse, double sampleRateToUse,
const BigInteger& ins, const BigInteger& outs);
void stopDevice();
void updateXml();
void createDeviceTypesIfNeeded();
void scanDevicesIfNeeded();
void deleteCurrentDevice();
double chooseBestSampleRate (double preferred) const;
int chooseBestBufferSize (int preferred) const;
void insertDefaultDeviceNames (AudioDeviceSetup&) const;
AudioIODeviceType* findType (const String& inputName, const String& outputName);
AudioIODeviceType* findType (const String& typeName);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioDeviceManager)
};
#endif // __JUCE_AUDIODEVICEMANAGER_JUCEHEADER__

+ 49
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp View File

@@ -0,0 +1,49 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
AudioIODevice::AudioIODevice (const String& deviceName, const String& typeName_)
: name (deviceName),
typeName (typeName_)
{
}
AudioIODevice::~AudioIODevice()
{
}
bool AudioIODevice::hasControlPanel() const
{
return false;
}
bool AudioIODevice::showControlPanel()
{
jassertfalse; // this should only be called for devices which return true from
// their hasControlPanel() method.
return false;
}
//==============================================================================
void AudioIODeviceCallback::audioDeviceError (const String&) {}

+ 333
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h View File

@@ -0,0 +1,333 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOIODEVICE_JUCEHEADER__
#define __JUCE_AUDIOIODEVICE_JUCEHEADER__
class AudioIODevice;
//==============================================================================
/**
One of these is passed to an AudioIODevice object to stream the audio data
in and out.
The AudioIODevice will repeatedly call this class's audioDeviceIOCallback()
method on its own high-priority audio thread, when it needs to send or receive
the next block of data.
@see AudioIODevice, AudioDeviceManager
*/
class JUCE_API AudioIODeviceCallback
{
public:
/** Destructor. */
virtual ~AudioIODeviceCallback() {}
/** Processes a block of incoming and outgoing audio data.
The subclass's implementation should use the incoming audio for whatever
purposes it needs to, and must fill all the output channels with the next
block of output data before returning.
The channel data is arranged with the same array indices as the channel name
array returned by AudioIODevice::getOutputChannelNames(), but those channels
that aren't specified in AudioIODevice::open() will have a null pointer for their
associated channel, so remember to check for this.
@param inputChannelData a set of arrays containing the audio data for each
incoming channel - this data is valid until the function
returns. There will be one channel of data for each input
channel that was enabled when the audio device was opened
(see AudioIODevice::open())
@param numInputChannels the number of pointers to channel data in the
inputChannelData array.
@param outputChannelData a set of arrays which need to be filled with the data
that should be sent to each outgoing channel of the device.
There will be one channel of data for each output channel
that was enabled when the audio device was opened (see
AudioIODevice::open())
The initial contents of the array is undefined, so the
callback function must fill all the channels with zeros if
its output is silence. Failing to do this could cause quite
an unpleasant noise!
@param numOutputChannels the number of pointers to channel data in the
outputChannelData array.
@param numSamples the number of samples in each channel of the input and
output arrays. The number of samples will depend on the
audio device's buffer size and will usually remain constant,
although this isn't guaranteed, so make sure your code can
cope with reasonable changes in the buffer size from one
callback to the next.
*/
virtual void audioDeviceIOCallback (const float** inputChannelData,
int numInputChannels,
float** outputChannelData,
int numOutputChannels,
int numSamples) = 0;
/** Called to indicate that the device is about to start calling back.
This will be called just before the audio callbacks begin, either when this
callback has just been added to an audio device, or after the device has been
restarted because of a sample-rate or block-size change.
You can use this opportunity to find out the sample rate and block size
that the device is going to use by calling the AudioIODevice::getCurrentSampleRate()
and AudioIODevice::getCurrentBufferSizeSamples() on the supplied pointer.
@param device the audio IO device that will be used to drive the callback.
Note that if you're going to store this this pointer, it is
only valid until the next time that audioDeviceStopped is called.
*/
virtual void audioDeviceAboutToStart (AudioIODevice* device) = 0;
/** Called to indicate that the device has stopped. */
virtual void audioDeviceStopped() = 0;
/** This can be overridden to be told if the device generates an error while operating.
Be aware that this could be called by any thread! And not all devices perform
this callback.
*/
virtual void audioDeviceError (const String& errorMessage);
};
//==============================================================================
/**
Base class for an audio device with synchronised input and output channels.
Subclasses of this are used to implement different protocols such as DirectSound,
ASIO, CoreAudio, etc.
To create one of these, you'll need to use the AudioIODeviceType class - see the
documentation for that class for more info.
For an easier way of managing audio devices and their settings, have a look at the
AudioDeviceManager class.
@see AudioIODeviceType, AudioDeviceManager
*/
class JUCE_API AudioIODevice
{
public:
/** Destructor. */
virtual ~AudioIODevice();
//==============================================================================
/** Returns the device's name, (as set in the constructor). */
const String& getName() const noexcept { return name; }
/** Returns the type of the device.
E.g. "CoreAudio", "ASIO", etc. - this comes from the AudioIODeviceType that created it.
*/
const String& getTypeName() const noexcept { return typeName; }
//==============================================================================
/** Returns the names of all the available output channels on this device.
To find out which of these are currently in use, call getActiveOutputChannels().
*/
virtual StringArray getOutputChannelNames() = 0;
/** Returns the names of all the available input channels on this device.
To find out which of these are currently in use, call getActiveInputChannels().
*/
virtual StringArray getInputChannelNames() = 0;
//==============================================================================
/** Returns the number of sample-rates this device supports.
To find out which rates are available on this device, use this method to
find out how many there are, and getSampleRate() to get the rates.
@see getSampleRate
*/
virtual int getNumSampleRates() = 0;
/** Returns one of the sample-rates this device supports.
To find out which rates are available on this device, use getNumSampleRates() to
find out how many there are, and getSampleRate() to get the individual rates.
The sample rate is set by the open() method.
(Note that for DirectSound some rates might not work, depending on combinations
of i/o channels that are being opened).
@see getNumSampleRates
*/
virtual double getSampleRate (int index) = 0;
/** Returns the number of sizes of buffer that are available.
@see getBufferSizeSamples, getDefaultBufferSize
*/
virtual int getNumBufferSizesAvailable() = 0;
/** Returns one of the possible buffer-sizes.
@param index the index of the buffer-size to use, from 0 to getNumBufferSizesAvailable() - 1
@returns a number of samples
@see getNumBufferSizesAvailable, getDefaultBufferSize
*/
virtual int getBufferSizeSamples (int index) = 0;
/** Returns the default buffer-size to use.
@returns a number of samples
@see getNumBufferSizesAvailable, getBufferSizeSamples
*/
virtual int getDefaultBufferSize() = 0;
//==============================================================================
/** Tries to open the device ready to play.
@param inputChannels a BigInteger in which a set bit indicates that the corresponding
input channel should be enabled
@param outputChannels a BigInteger in which a set bit indicates that the corresponding
output channel should be enabled
@param sampleRate the sample rate to try to use - to find out which rates are
available, see getNumSampleRates() and getSampleRate()
@param bufferSizeSamples the size of i/o buffer to use - to find out the available buffer
sizes, see getNumBufferSizesAvailable() and getBufferSizeSamples()
@returns an error description if there's a problem, or an empty string if it succeeds in
opening the device
@see close
*/
virtual String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double sampleRate,
int bufferSizeSamples) = 0;
/** Closes and releases the device if it's open. */
virtual void close() = 0;
/** Returns true if the device is still open.
A device might spontaneously close itself if something goes wrong, so this checks if
it's still open.
*/
virtual bool isOpen() = 0;
/** Starts the device actually playing.
This must be called after the device has been opened.
@param callback the callback to use for streaming the data.
@see AudioIODeviceCallback, open
*/
virtual void start (AudioIODeviceCallback* callback) = 0;
/** Stops the device playing.
Once a device has been started, this will stop it. Any pending calls to the
callback class will be flushed before this method returns.
*/
virtual void stop() = 0;
/** Returns true if the device is still calling back.
The device might mysteriously stop, so this checks whether it's
still playing.
*/
virtual bool isPlaying() = 0;
/** Returns the last error that happened if anything went wrong. */
virtual String getLastError() = 0;
//==============================================================================
/** Returns the buffer size that the device is currently using.
If the device isn't actually open, this value doesn't really mean much.
*/
virtual int getCurrentBufferSizeSamples() = 0;
/** Returns the sample rate that the device is currently using.
If the device isn't actually open, this value doesn't really mean much.
*/
virtual double getCurrentSampleRate() = 0;
/** Returns the device's current physical bit-depth.
If the device isn't actually open, this value doesn't really mean much.
*/
virtual int getCurrentBitDepth() = 0;
/** Returns a mask showing which of the available output channels are currently
enabled.
@see getOutputChannelNames
*/
virtual BigInteger getActiveOutputChannels() const = 0;
/** Returns a mask showing which of the available input channels are currently
enabled.
@see getInputChannelNames
*/
virtual BigInteger getActiveInputChannels() const = 0;
/** Returns the device's output latency.
This is the delay in samples between a callback getting a block of data, and
that data actually getting played.
*/
virtual int getOutputLatencyInSamples() = 0;
/** Returns the device's input latency.
This is the delay in samples between some audio actually arriving at the soundcard,
and the callback getting passed this block of data.
*/
virtual int getInputLatencyInSamples() = 0;
//==============================================================================
/** True if this device can show a pop-up control panel for editing its settings.
This is generally just true of ASIO devices. If true, you can call showControlPanel()
to display it.
*/
virtual bool hasControlPanel() const;
/** Shows a device-specific control panel if there is one.
This should only be called for devices which return true from hasControlPanel().
*/
virtual bool showControlPanel();
//==============================================================================
protected:
/** Creates a device, setting its name and type member variables. */
AudioIODevice (const String& deviceName,
const String& typeName);
/** @internal */
String name, typeName;
};
#endif // __JUCE_AUDIOIODEVICE_JUCEHEADER__

+ 79
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.cpp View File

@@ -0,0 +1,79 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
AudioIODeviceType::AudioIODeviceType (const String& name)
: typeName (name)
{
}
AudioIODeviceType::~AudioIODeviceType()
{
}
//==============================================================================
void AudioIODeviceType::addListener (Listener* l) { listeners.add (l); }
void AudioIODeviceType::removeListener (Listener* l) { listeners.remove (l); }
void AudioIODeviceType::callDeviceChangeListeners()
{
listeners.call (&AudioIODeviceType::Listener::audioDeviceListChanged);
}
//==============================================================================
#if ! JUCE_MAC
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_CoreAudio() { return nullptr; }
#endif
#if ! JUCE_IOS
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_iOSAudio() { return nullptr; }
#endif
#if ! (JUCE_WINDOWS && JUCE_WASAPI)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI() { return nullptr; }
#endif
#if ! (JUCE_WINDOWS && JUCE_DIRECTSOUND)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_DirectSound() { return nullptr; }
#endif
#if ! (JUCE_WINDOWS && JUCE_ASIO)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ASIO() { return nullptr; }
#endif
#if ! (JUCE_LINUX && JUCE_ALSA)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ALSA() { return nullptr; }
#endif
#if ! (JUCE_LINUX && JUCE_JACK)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_JACK() { return nullptr; }
#endif
#if ! JUCE_ANDROID
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Android() { return nullptr; }
#endif
#if ! (JUCE_ANDROID && JUCE_USE_ANDROID_OPENSLES)
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_OpenSLES() { return nullptr; }
#endif

+ 186
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h View File

@@ -0,0 +1,186 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOIODEVICETYPE_JUCEHEADER__
#define __JUCE_AUDIOIODEVICETYPE_JUCEHEADER__
#include "juce_AudioIODevice.h"
class AudioDeviceManager;
//==============================================================================
/**
Represents a type of audio driver, such as DirectSound, ASIO, CoreAudio, etc.
To get a list of available audio driver types, use the AudioDeviceManager::createAudioDeviceTypes()
method. Each of the objects returned can then be used to list the available
devices of that type. E.g.
@code
OwnedArray <AudioIODeviceType> types;
myAudioDeviceManager.createAudioDeviceTypes (types);
for (int i = 0; i < types.size(); ++i)
{
String typeName (types[i]->getTypeName()); // This will be things like "DirectSound", "CoreAudio", etc.
types[i]->scanForDevices(); // This must be called before getting the list of devices
StringArray deviceNames (types[i]->getDeviceNames()); // This will now return a list of available devices of this type
for (int j = 0; j < deviceNames.size(); ++j)
{
AudioIODevice* device = types[i]->createDevice (deviceNames [j]);
...
}
}
@endcode
For an easier way of managing audio devices and their settings, have a look at the
AudioDeviceManager class.
@see AudioIODevice, AudioDeviceManager
*/
class JUCE_API AudioIODeviceType
{
public:
//==============================================================================
/** Returns the name of this type of driver that this object manages.
This will be something like "DirectSound", "ASIO", "CoreAudio", "ALSA", etc.
*/
const String& getTypeName() const noexcept { return typeName; }
//==============================================================================
/** Refreshes the object's cached list of known devices.
This must be called at least once before calling getDeviceNames() or any of
the other device creation methods.
*/
virtual void scanForDevices() = 0;
/** Returns the list of available devices of this type.
The scanForDevices() method must have been called to create this list.
@param wantInputNames only really used by DirectSound where devices are split up
into inputs and outputs, this indicates whether to use
the input or output name to refer to a pair of devices.
*/
virtual StringArray getDeviceNames (bool wantInputNames = false) const = 0;
/** Returns the name of the default device.
This will be one of the names from the getDeviceNames() list.
@param forInput if true, this means that a default input device should be
returned; if false, it should return the default output
*/
virtual int getDefaultDeviceIndex (bool forInput) const = 0;
/** Returns the index of a given device in the list of device names.
If asInput is true, it shows the index in the inputs list, otherwise it
looks for it in the outputs list.
*/
virtual int getIndexOfDevice (AudioIODevice* device, bool asInput) const = 0;
/** Returns true if two different devices can be used for the input and output.
*/
virtual bool hasSeparateInputsAndOutputs() const = 0;
/** Creates one of the devices of this type.
The deviceName must be one of the strings returned by getDeviceNames(), and
scanForDevices() must have been called before this method is used.
*/
virtual AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName) = 0;
//==============================================================================
/**
A class for receiving events when audio devices are inserted or removed.
You can register a AudioIODeviceType::Listener with an~AudioIODeviceType object
using the AudioIODeviceType::addListener() method, and it will be called when
devices of that type are added or removed.
@see AudioIODeviceType::addListener, AudioIODeviceType::removeListener
*/
class Listener
{
public:
virtual ~Listener() {}
/** Called when the list of available audio devices changes. */
virtual void audioDeviceListChanged() = 0;
};
/** Adds a listener that will be called when this type of device is added or
removed from the system.
*/
void addListener (Listener* listener);
/** Removes a listener that was previously added with addListener(). */
void removeListener (Listener* listener);
//==============================================================================
/** Destructor. */
virtual ~AudioIODeviceType();
//==============================================================================
/** Creates a CoreAudio device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_CoreAudio();
/** Creates an iOS device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_iOSAudio();
/** Creates a WASAPI device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_WASAPI();
/** Creates a DirectSound device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_DirectSound();
/** Creates an ASIO device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_ASIO();
/** Creates an ALSA device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_ALSA();
/** Creates a JACK device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_JACK();
/** Creates an Android device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_Android();
/** Creates an Android OpenSLES device type if it's available on this platform, or returns null. */
static AudioIODeviceType* createAudioIODeviceType_OpenSLES();
protected:
explicit AudioIODeviceType (const String& typeName);
/** Synchronously calls all the registered device list change listeners. */
void callDeviceChangeListeners();
private:
String typeName;
ListenerList<Listener> listeners;
JUCE_DECLARE_NON_COPYABLE (AudioIODeviceType)
};
#endif // __JUCE_AUDIOIODEVICETYPE_JUCEHEADER__

+ 236
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.cpp View File

@@ -0,0 +1,236 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#if defined (__JUCE_AUDIO_DEVICES_JUCEHEADER__) && ! JUCE_AMALGAMATED_INCLUDE
/* When you add this cpp file to your project, you mustn't include it in a file where you've
already included any other headers - just put it inside a file on its own, possibly with your config
flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
header files that the compiler may be using.
*/
#error "Incorrect use of JUCE cpp file"
#endif
// Your project must contain an AppConfig.h file with your project-specific settings in it,
// and your header search path must make it accessible to the module's files.
#include "AppConfig.h"
#include "../juce_core/native/juce_BasicNativeHeaders.h"
#include "juce_audio_devices.h"
//==============================================================================
#if JUCE_MAC
#define Point CarbonDummyPointName
#define Component CarbonDummyCompName
#import <CoreAudio/AudioHardware.h>
#import <CoreMIDI/MIDIServices.h>
#import <DiscRecording/DiscRecording.h>
#undef Point
#undef Component
#elif JUCE_IOS
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreMIDI/MIDIServices.h>
//==============================================================================
#elif JUCE_WINDOWS
#if JUCE_WASAPI
#pragma warning (push)
#pragma warning (disable: 4201)
#include <MMReg.h>
#include <Audioclient.h>
#include <Audiopolicy.h>
#include <Avrt.h>
#include <functiondiscoverykeys.h>
#pragma warning (pop)
#endif
#if JUCE_ASIO
/* This is very frustrating - we only need to use a handful of definitions from
a couple of the header files in Steinberg's ASIO SDK, and it'd be easy to copy
about 30 lines of code into this cpp file to create a fully stand-alone ASIO
implementation...
..unfortunately that would break Steinberg's license agreement for use of
their SDK, so I'm not allowed to do this.
This means that anyone who wants to use JUCE's ASIO abilities will have to:
1) Agree to Steinberg's licensing terms and download the ASIO SDK
(see www.steinberg.net/Steinberg/Developers.asp).
2) Enable this code with a global definition #define JUCE_ASIO 1.
3) Make sure that your header search path contains the iasiodrv.h file that
comes with the SDK. (Only about a handful of the SDK header files are actually
needed - so to simplify things, you could just copy these into your JUCE directory).
*/
#include <iasiodrv.h>
#endif
#if JUCE_USE_CDBURNER
/* You'll need the Platform SDK for these headers - if you don't have it and don't
need to use CD-burning, then you might just want to set the JUCE_USE_CDBURNER flag
to 0, to avoid these includes.
*/
#include <imapi.h>
#include <imapierror.h>
#endif
//==============================================================================
#elif JUCE_LINUX
#if JUCE_ALSA
/* Got an include error here? If so, you've either not got ALSA installed, or you've
not got your paths set up correctly to find its header files.
The package you need to install to get ASLA support is "libasound2-dev".
If you don't have the ALSA library and don't want to build Juce with audio support,
just set the JUCE_ALSA flag to 0.
*/
#include <alsa/asoundlib.h>
#endif
#if JUCE_JACK
/* Got an include error here? If so, you've either not got jack-audio-connection-kit
installed, or you've not got your paths set up correctly to find its header files.
The package you need to install to get JACK support is "libjack-dev".
If you don't have the jack-audio-connection-kit library and don't want to build
Juce with low latency audio support, just set the JUCE_JACK flag to 0.
*/
#include <jack/jack.h>
#endif
#undef SIZEOF
//==============================================================================
#elif JUCE_ANDROID
#if JUCE_USE_ANDROID_OPENSLES
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#endif
#endif
namespace juce
{
// START_AUTOINCLUDE audio_io/*.cpp, midi_io/*.cpp, audio_cd/*.cpp, sources/*.cpp
#include "audio_io/juce_AudioDeviceManager.cpp"
#include "audio_io/juce_AudioIODevice.cpp"
#include "audio_io/juce_AudioIODeviceType.cpp"
#include "midi_io/juce_MidiMessageCollector.cpp"
#include "midi_io/juce_MidiOutput.cpp"
#include "audio_cd/juce_AudioCDReader.cpp"
#include "sources/juce_AudioSourcePlayer.cpp"
#include "sources/juce_AudioTransportSource.cpp"
// END_AUTOINCLUDE
}
//==============================================================================
using namespace juce;
namespace juce
{
#include "native/juce_MidiDataConcatenator.h"
//==============================================================================
#if JUCE_MAC
#include "../juce_core/native/juce_osx_ObjCHelpers.h"
#include "native/juce_mac_CoreAudio.cpp"
#include "native/juce_mac_CoreMidi.cpp"
#if JUCE_USE_CDREADER
#include "native/juce_mac_AudioCDReader.mm"
#endif
#if JUCE_USE_CDBURNER
#include "native/juce_mac_AudioCDBurner.mm"
#endif
//==============================================================================
#elif JUCE_IOS
#include "native/juce_ios_Audio.cpp"
#include "native/juce_mac_CoreMidi.cpp"
//==============================================================================
#elif JUCE_WINDOWS
#include "../juce_core/native/juce_win32_ComSmartPtr.h"
#include "../juce_events/native/juce_win32_HiddenMessageWindow.h"
#if JUCE_WASAPI
#include "native/juce_win32_WASAPI.cpp"
#endif
#if JUCE_DIRECTSOUND
#include "native/juce_win32_DirectSound.cpp"
#endif
#include "native/juce_win32_Midi.cpp"
#if JUCE_ASIO
#include "native/juce_win32_ASIO.cpp"
#endif
#if JUCE_USE_CDREADER
#include "native/juce_win32_AudioCDReader.cpp"
#endif
#if JUCE_USE_CDBURNER
#include "native/juce_win32_AudioCDBurner.cpp"
#endif
//==============================================================================
#elif JUCE_LINUX
#if JUCE_ALSA
#include "native/juce_linux_ALSA.cpp"
#endif
#include "native/juce_linux_Midi.cpp"
#if JUCE_JACK
#include "native/juce_linux_JackAudio.cpp"
#endif
#if JUCE_USE_CDREADER
#include "native/juce_linux_AudioCDReader.cpp"
#endif
//==============================================================================
#elif JUCE_ANDROID
#include "../juce_core/native/juce_android_JNIHelpers.h"
#include "native/juce_android_Audio.cpp"
#include "native/juce_android_Midi.cpp"
#if JUCE_USE_ANDROID_OPENSLES
#include "native/juce_android_OpenSL.cpp"
#endif
#endif
}

+ 139
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h View File

@@ -0,0 +1,139 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIO_DEVICES_JUCEHEADER__
#define __JUCE_AUDIO_DEVICES_JUCEHEADER__
#include "../juce_events/juce_events.h"
#include "../juce_audio_basics/juce_audio_basics.h"
#include "../juce_audio_formats/juce_audio_formats.h"
//=============================================================================
/** Config: JUCE_ASIO
Enables ASIO audio devices (MS Windows only).
Turning this on means that you'll need to have the Steinberg ASIO SDK installed
on your Windows build machine.
See the comments in the ASIOAudioIODevice class's header file for more
info about this.
*/
#ifndef JUCE_ASIO
#define JUCE_ASIO 0
#endif
/** Config: JUCE_WASAPI
Enables WASAPI audio devices (Windows Vista and above).
*/
#ifndef JUCE_WASAPI
#define JUCE_WASAPI 1
#endif
/** Config: JUCE_DIRECTSOUND
Enables DirectSound audio (MS Windows only).
*/
#ifndef JUCE_DIRECTSOUND
#define JUCE_DIRECTSOUND 1
#endif
/** Config: JUCE_ALSA
Enables ALSA audio devices (Linux only).
*/
#ifndef JUCE_ALSA
#define JUCE_ALSA 1
#endif
/** Config: JUCE_JACK
Enables JACK audio devices (Linux only).
*/
#ifndef JUCE_JACK
#define JUCE_JACK 0
#endif
/** Config: JUCE_USE_ANDROID_OPENSLES
Enables OpenSLES devices (Android only).
*/
#ifndef JUCE_USE_ANDROID_OPENSLES
#if JUCE_ANDROID_API_VERSION > 8
#define JUCE_USE_ANDROID_OPENSLES 1
#else
#define JUCE_USE_ANDROID_OPENSLES 0
#endif
#endif
//=============================================================================
/** Config: JUCE_USE_CDREADER
Enables the AudioCDReader class (on supported platforms).
*/
#ifndef JUCE_USE_CDREADER
#define JUCE_USE_CDREADER 0
#endif
/** Config: JUCE_USE_CDBURNER
Enables the AudioCDBurner class (on supported platforms).
*/
#ifndef JUCE_USE_CDBURNER
#define JUCE_USE_CDBURNER 0
#endif
//=============================================================================
namespace juce
{
// START_AUTOINCLUDE audio_io, midi_io, sources, audio_cd
#ifndef __JUCE_AUDIODEVICEMANAGER_JUCEHEADER__
#include "audio_io/juce_AudioDeviceManager.h"
#endif
#ifndef __JUCE_AUDIOIODEVICE_JUCEHEADER__
#include "audio_io/juce_AudioIODevice.h"
#endif
#ifndef __JUCE_AUDIOIODEVICETYPE_JUCEHEADER__
#include "audio_io/juce_AudioIODeviceType.h"
#endif
#ifndef __JUCE_MIDIINPUT_JUCEHEADER__
#include "midi_io/juce_MidiInput.h"
#endif
#ifndef __JUCE_MIDIMESSAGECOLLECTOR_JUCEHEADER__
#include "midi_io/juce_MidiMessageCollector.h"
#endif
#ifndef __JUCE_MIDIOUTPUT_JUCEHEADER__
#include "midi_io/juce_MidiOutput.h"
#endif
#ifndef __JUCE_AUDIOSOURCEPLAYER_JUCEHEADER__
#include "sources/juce_AudioSourcePlayer.h"
#endif
#ifndef __JUCE_AUDIOTRANSPORTSOURCE_JUCEHEADER__
#include "sources/juce_AudioTransportSource.h"
#endif
#ifndef __JUCE_AUDIOCDBURNER_JUCEHEADER__
#include "audio_cd/juce_AudioCDBurner.h"
#endif
#ifndef __JUCE_AUDIOCDREADER_JUCEHEADER__
#include "audio_cd/juce_AudioCDReader.h"
#endif
// END_AUTOINCLUDE
}
#endif // __JUCE_AUDIO_DEVICES_JUCEHEADER__

+ 26
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.mm View File

@@ -0,0 +1,26 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#include "juce_audio_devices.cpp"

+ 27
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/juce_module_info View File

@@ -0,0 +1,27 @@
{
"id": "juce_audio_devices",
"name": "JUCE audio and midi I/O device classes",
"version": "2.0.32",
"description": "Classes to play and record from audio and midi i/o devices.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",
"dependencies": [ { "id": "juce_audio_basics", "version": "matching" },
{ "id": "juce_audio_formats", "version": "matching" },
{ "id": "juce_events", "version": "matching" } ],
"include": "juce_audio_devices.h",
"compile": [ { "file": "juce_audio_devices.cpp", "target": "! xcode" },
{ "file": "juce_audio_devices.mm", "target": "xcode" } ],
"browse": [ "audio_io/*",
"midi_io/*",
"sources/*",
"audio_cd/*",
"native/*" ],
"OSXFrameworks": "CoreAudio CoreMIDI DiscRecording",
"iOSFrameworks": "AudioToolbox CoreMIDI",
"LinuxLibs": "asound"
}

+ 183
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiInput.h View File

@@ -0,0 +1,183 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIINPUT_JUCEHEADER__
#define __JUCE_MIDIINPUT_JUCEHEADER__
class MidiInput;
//==============================================================================
/**
Receives incoming messages from a physical MIDI input device.
This class is overridden to handle incoming midi messages. See the MidiInput
class for more details.
@see MidiInput
*/
class JUCE_API MidiInputCallback
{
public:
/** Destructor. */
virtual ~MidiInputCallback() {}
/** Receives an incoming message.
A MidiInput object will call this method when a midi event arrives. It'll be
called on a high-priority system thread, so avoid doing anything time-consuming
in here, and avoid making any UI calls. You might find the MidiBuffer class helpful
for queueing incoming messages for use later.
@param source the MidiInput object that generated the message
@param message the incoming message. The message's timestamp is set to a value
equivalent to (Time::getMillisecondCounter() / 1000.0) to specify the
time when the message arrived.
*/
virtual void handleIncomingMidiMessage (MidiInput* source,
const MidiMessage& message) = 0;
/** Notification sent each time a packet of a multi-packet sysex message arrives.
If a long sysex message is broken up into multiple packets, this callback is made
for each packet that arrives until the message is finished, at which point
the normal handleIncomingMidiMessage() callback will be made with the entire
message.
The message passed in will contain the start of a sysex, but won't be finished
with the terminating 0xf7 byte.
*/
virtual void handlePartialSysexMessage (MidiInput* source,
const uint8* messageData,
int numBytesSoFar,
double timestamp)
{
// (this bit is just to avoid compiler warnings about unused variables)
(void) source; (void) messageData; (void) numBytesSoFar; (void) timestamp;
}
};
//==============================================================================
/**
Represents a midi input device.
To create one of these, use the static getDevices() method to find out what inputs are
available, and then use the openDevice() method to try to open one.
@see MidiOutput
*/
class JUCE_API MidiInput
{
public:
//==============================================================================
/** Returns a list of the available midi input devices.
You can open one of the devices by passing its index into the
openDevice() method.
@see getDefaultDeviceIndex, openDevice
*/
static StringArray getDevices();
/** Returns the index of the default midi input device to use.
This refers to the index in the list returned by getDevices().
*/
static int getDefaultDeviceIndex();
/** Tries to open one of the midi input devices.
This will return a MidiInput object if it manages to open it. You can then
call start() and stop() on this device, and delete it when no longer needed.
If the device can't be opened, this will return a null pointer.
@param deviceIndex the index of a device from the list returned by getDevices()
@param callback the object that will receive the midi messages from this device.
@see MidiInputCallback, getDevices
*/
static MidiInput* openDevice (int deviceIndex,
MidiInputCallback* callback);
#if JUCE_LINUX || JUCE_MAC || JUCE_IOS || DOXYGEN
/** This will try to create a new midi input device (Not available on Windows).
This will attempt to create a new midi input device with the specified name,
for other apps to connect to.
Returns nullptr if a device can't be created.
@param deviceName the name to use for the new device
@param callback the object that will receive the midi messages from this device.
*/
static MidiInput* createNewDevice (const String& deviceName,
MidiInputCallback* callback);
#endif
//==============================================================================
/** Destructor. */
virtual ~MidiInput();
/** Returns the name of this device. */
const String& getName() const noexcept { return name; }
/** Allows you to set a custom name for the device, in case you don't like the name
it was given when created.
*/
void setName (const String& newName) noexcept { name = newName; }
//==============================================================================
/** Starts the device running.
After calling this, the device will start sending midi messages to the
MidiInputCallback object that was specified when the openDevice() method
was called.
@see stop
*/
virtual void start();
/** Stops the device running.
@see start
*/
virtual void stop();
protected:
//==============================================================================
String name;
void* internal;
explicit MidiInput (const String& name);
private:
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiInput)
};
#endif // __JUCE_MIDIINPUT_JUCEHEADER__

+ 153
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp View File

@@ -0,0 +1,153 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
MidiMessageCollector::MidiMessageCollector()
: lastCallbackTime (0),
sampleRate (44100.0001)
{
}
MidiMessageCollector::~MidiMessageCollector()
{
}
//==============================================================================
void MidiMessageCollector::reset (const double sampleRate_)
{
jassert (sampleRate_ > 0);
const ScopedLock sl (midiCallbackLock);
sampleRate = sampleRate_;
incomingMessages.clear();
lastCallbackTime = Time::getMillisecondCounterHiRes();
}
void MidiMessageCollector::addMessageToQueue (const MidiMessage& message)
{
// you need to call reset() to set the correct sample rate before using this object
jassert (sampleRate != 44100.0001);
// the messages that come in here need to be time-stamped correctly - see MidiInput
// for details of what the number should be.
jassert (message.getTimeStamp() != 0);
const ScopedLock sl (midiCallbackLock);
const int sampleNumber
= (int) ((message.getTimeStamp() - 0.001 * lastCallbackTime) * sampleRate);
incomingMessages.addEvent (message, sampleNumber);
// if the messages don't get used for over a second, we'd better
// get rid of any old ones to avoid the queue getting too big
if (sampleNumber > sampleRate)
incomingMessages.clear (0, sampleNumber - (int) sampleRate);
}
void MidiMessageCollector::removeNextBlockOfMessages (MidiBuffer& destBuffer,
const int numSamples)
{
// you need to call reset() to set the correct sample rate before using this object
jassert (sampleRate != 44100.0001);
const double timeNow = Time::getMillisecondCounterHiRes();
const double msElapsed = timeNow - lastCallbackTime;
const ScopedLock sl (midiCallbackLock);
lastCallbackTime = timeNow;
if (! incomingMessages.isEmpty())
{
int numSourceSamples = jmax (1, roundToInt (msElapsed * 0.001 * sampleRate));
int startSample = 0;
int scale = 1 << 16;
const uint8* midiData;
int numBytes, samplePosition;
MidiBuffer::Iterator iter (incomingMessages);
if (numSourceSamples > numSamples)
{
// if our list of events is longer than the buffer we're being
// asked for, scale them down to squeeze them all in..
const int maxBlockLengthToUse = numSamples << 5;
if (numSourceSamples > maxBlockLengthToUse)
{
startSample = numSourceSamples - maxBlockLengthToUse;
numSourceSamples = maxBlockLengthToUse;
iter.setNextSamplePosition (startSample);
}
scale = (numSamples << 10) / numSourceSamples;
while (iter.getNextEvent (midiData, numBytes, samplePosition))
{
samplePosition = ((samplePosition - startSample) * scale) >> 10;
destBuffer.addEvent (midiData, numBytes,
jlimit (0, numSamples - 1, samplePosition));
}
}
else
{
// if our event list is shorter than the number we need, put them
// towards the end of the buffer
startSample = numSamples - numSourceSamples;
while (iter.getNextEvent (midiData, numBytes, samplePosition))
{
destBuffer.addEvent (midiData, numBytes,
jlimit (0, numSamples - 1, samplePosition + startSample));
}
}
incomingMessages.clear();
}
}
//==============================================================================
void MidiMessageCollector::handleNoteOn (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity)
{
MidiMessage m (MidiMessage::noteOn (midiChannel, midiNoteNumber, velocity));
m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
addMessageToQueue (m);
}
void MidiMessageCollector::handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber)
{
MidiMessage m (MidiMessage::noteOff (midiChannel, midiNoteNumber));
m.setTimeStamp (Time::getMillisecondCounterHiRes() * 0.001);
addMessageToQueue (m);
}
void MidiMessageCollector::handleIncomingMidiMessage (MidiInput*, const MidiMessage& message)
{
addMessageToQueue (message);
}

+ 105
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h View File

@@ -0,0 +1,105 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIMESSAGECOLLECTOR_JUCEHEADER__
#define __JUCE_MIDIMESSAGECOLLECTOR_JUCEHEADER__
#include "juce_MidiInput.h"
//==============================================================================
/**
Collects incoming realtime MIDI messages and turns them into blocks suitable for
processing by a block-based audio callback.
The class can also be used as either a MidiKeyboardStateListener or a MidiInputCallback
so it can easily use a midi input or keyboard component as its source.
@see MidiMessage, MidiInput
*/
class JUCE_API MidiMessageCollector : public MidiKeyboardStateListener,
public MidiInputCallback
{
public:
//==============================================================================
/** Creates a MidiMessageCollector. */
MidiMessageCollector();
/** Destructor. */
~MidiMessageCollector();
//==============================================================================
/** Clears any messages from the queue.
You need to call this method before starting to use the collector, so that
it knows the correct sample rate to use.
*/
void reset (double sampleRate);
/** Takes an incoming real-time message and adds it to the queue.
The message's timestamp is taken, and it will be ready for retrieval as part
of the block returned by the next call to removeNextBlockOfMessages().
This method is fully thread-safe when overlapping calls are made with
removeNextBlockOfMessages().
*/
void addMessageToQueue (const MidiMessage& message);
/** Removes all the pending messages from the queue as a buffer.
This will also correct the messages' timestamps to make sure they're in
the range 0 to numSamples - 1.
This call should be made regularly by something like an audio processing
callback, because the time that it happens is used in calculating the
midi event positions.
This method is fully thread-safe when overlapping calls are made with
addMessageToQueue().
*/
void removeNextBlockOfMessages (MidiBuffer& destBuffer, int numSamples);
//==============================================================================
/** @internal */
void handleNoteOn (MidiKeyboardState* source, int midiChannel, int midiNoteNumber, float velocity);
/** @internal */
void handleNoteOff (MidiKeyboardState* source, int midiChannel, int midiNoteNumber);
/** @internal */
void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message);
private:
//==============================================================================
double lastCallbackTime;
CriticalSection midiCallbackLock;
MidiBuffer incomingMessages;
double sampleRate;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiMessageCollector)
};
#endif // __JUCE_MIDIMESSAGECOLLECTOR_JUCEHEADER__

+ 163
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.cpp View File

@@ -0,0 +1,163 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
struct MidiOutput::PendingMessage
{
PendingMessage (const void* const data, const int len, const double timeStamp)
: message (data, len, timeStamp)
{}
MidiMessage message;
PendingMessage* next;
};
MidiOutput::MidiOutput()
: Thread ("midi out"),
internal (nullptr),
firstMessage (nullptr)
{
}
void MidiOutput::sendBlockOfMessages (const MidiBuffer& buffer,
const double millisecondCounterToStartAt,
double samplesPerSecondForBuffer)
{
// You've got to call startBackgroundThread() for this to actually work..
jassert (isThreadRunning());
// this needs to be a value in the future - RTFM for this method!
jassert (millisecondCounterToStartAt > 0);
const double timeScaleFactor = 1000.0 / samplesPerSecondForBuffer;
MidiBuffer::Iterator i (buffer);
const uint8* data;
int len, time;
while (i.getNextEvent (data, len, time))
{
const double eventTime = millisecondCounterToStartAt + timeScaleFactor * time;
PendingMessage* const m = new PendingMessage (data, len, eventTime);
const ScopedLock sl (lock);
if (firstMessage == nullptr || firstMessage->message.getTimeStamp() > eventTime)
{
m->next = firstMessage;
firstMessage = m;
}
else
{
PendingMessage* mm = firstMessage;
while (mm->next != nullptr && mm->next->message.getTimeStamp() <= eventTime)
mm = mm->next;
m->next = mm->next;
mm->next = m;
}
}
notify();
}
void MidiOutput::clearAllPendingMessages()
{
const ScopedLock sl (lock);
while (firstMessage != nullptr)
{
PendingMessage* const m = firstMessage;
firstMessage = firstMessage->next;
delete m;
}
}
void MidiOutput::startBackgroundThread()
{
startThread (9);
}
void MidiOutput::stopBackgroundThread()
{
stopThread (5000);
}
void MidiOutput::run()
{
while (! threadShouldExit())
{
uint32 now = Time::getMillisecondCounter();
uint32 eventTime = 0;
uint32 timeToWait = 500;
PendingMessage* message;
{
const ScopedLock sl (lock);
message = firstMessage;
if (message != nullptr)
{
eventTime = (uint32) roundToInt (message->message.getTimeStamp());
if (eventTime > now + 20)
{
timeToWait = eventTime - (now + 20);
message = nullptr;
}
else
{
firstMessage = message->next;
}
}
}
if (message != nullptr)
{
const ScopedPointer<PendingMessage> messageDeleter (message);
if (eventTime > now)
{
Time::waitForMillisecondCounter (eventTime);
if (threadShouldExit())
break;
}
if (eventTime > now - 200)
sendMessageNow (message->message);
}
else
{
jassert (timeToWait < 1000 * 30);
wait ((int) timeToWait);
}
}
clearAllPendingMessages();
}

+ 148
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.h View File

@@ -0,0 +1,148 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIOUTPUT_JUCEHEADER__
#define __JUCE_MIDIOUTPUT_JUCEHEADER__
//==============================================================================
/**
Controls a physical MIDI output device.
To create one of these, use the static getDevices() method to get a list of the
available output devices, then use the openDevice() method to try to open one.
@see MidiInput
*/
class JUCE_API MidiOutput : private Thread
{
public:
//==============================================================================
/** Returns a list of the available midi output devices.
You can open one of the devices by passing its index into the
openDevice() method.
@see getDefaultDeviceIndex, openDevice
*/
static StringArray getDevices();
/** Returns the index of the default midi output device to use.
This refers to the index in the list returned by getDevices().
*/
static int getDefaultDeviceIndex();
/** Tries to open one of the midi output devices.
This will return a MidiOutput object if it manages to open it. You can then
send messages to this device, and delete it when no longer needed.
If the device can't be opened, this will return a null pointer.
@param deviceIndex the index of a device from the list returned by getDevices()
@see getDevices
*/
static MidiOutput* openDevice (int deviceIndex);
#if JUCE_LINUX || JUCE_MAC || JUCE_IOS || DOXYGEN
/** This will try to create a new midi output device (Not available on Windows).
This will attempt to create a new midi output device that other apps can connect
to and use as their midi input.
Returns nullptr if a device can't be created.
@param deviceName the name to use for the new device
*/
static MidiOutput* createNewDevice (const String& deviceName);
#endif
//==============================================================================
/** Destructor. */
virtual ~MidiOutput();
/** Makes this device output a midi message.
@see MidiMessage
*/
virtual void sendMessageNow (const MidiMessage& message);
//==============================================================================
/** This lets you supply a block of messages that will be sent out at some point
in the future.
The MidiOutput class has an internal thread that can send out timestamped
messages - this appends a set of messages to its internal buffer, ready for
sending.
This will only work if you've already started the thread with startBackgroundThread().
A time is supplied, at which the block of messages should be sent. This time uses
the same time base as Time::getMillisecondCounter(), and must be in the future.
The samplesPerSecondForBuffer parameter indicates the number of samples per second
used by the MidiBuffer. Each event in a MidiBuffer has a sample position, and the
samplesPerSecondForBuffer value is needed to convert this sample position to a
real time.
*/
virtual void sendBlockOfMessages (const MidiBuffer& buffer,
double millisecondCounterToStartAt,
double samplesPerSecondForBuffer);
/** Gets rid of any midi messages that had been added by sendBlockOfMessages().
*/
virtual void clearAllPendingMessages();
/** Starts up a background thread so that the device can send blocks of data.
Call this to get the device ready, before using sendBlockOfMessages().
*/
virtual void startBackgroundThread();
/** Stops the background thread, and clears any pending midi events.
@see startBackgroundThread
*/
virtual void stopBackgroundThread();
protected:
//==============================================================================
void* internal;
CriticalSection lock;
struct PendingMessage;
PendingMessage* firstMessage;
MidiOutput();
void run();
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiOutput)
};
#endif // __JUCE_MIDIOUTPUT_JUCEHEADER__

+ 176
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h View File

@@ -0,0 +1,176 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_MIDIDATACONCATENATOR_JUCEHEADER__
#define __JUCE_MIDIDATACONCATENATOR_JUCEHEADER__
//==============================================================================
/**
Helper class that takes chunks of incoming midi bytes, packages them into
messages, and dispatches them to a midi callback.
*/
class MidiDataConcatenator
{
public:
//==============================================================================
MidiDataConcatenator (const int initialBufferSize)
: pendingData ((size_t) initialBufferSize),
pendingDataTime (0), pendingBytes (0), runningStatus (0)
{
}
void reset()
{
pendingBytes = 0;
runningStatus = 0;
pendingDataTime = 0;
}
template <typename UserDataType, typename CallbackType>
void pushMidiData (const void* inputData, int numBytes, double time,
UserDataType* input, CallbackType& callback)
{
const uint8* d = static_cast <const uint8*> (inputData);
while (numBytes > 0)
{
if (pendingBytes > 0 || d[0] == 0xf0)
{
processSysex (d, numBytes, time, input, callback);
runningStatus = 0;
}
else
{
int len = 0;
uint8 data[3];
while (numBytes > 0)
{
// If there's a realtime message embedded in the middle of
// the normal message, handle it now..
if (*d >= 0xf8 && *d <= 0xfe)
{
const MidiMessage m (*d++, time);
callback.handleIncomingMidiMessage (input, m);
--numBytes;
}
else
{
if (len == 0 && *d < 0x80 && runningStatus >= 0x80)
data[len++] = runningStatus;
data[len++] = *d++;
--numBytes;
if (len >= MidiMessage::getMessageLengthFromFirstByte (data[0]))
break;
}
}
if (len > 0)
{
int used = 0;
const MidiMessage m (data, len, used, 0, time);
if (used <= 0)
break; // malformed message..
jassert (used == len);
callback.handleIncomingMidiMessage (input, m);
runningStatus = data[0];
}
}
}
}
private:
template <typename UserDataType, typename CallbackType>
void processSysex (const uint8*& d, int& numBytes, double time,
UserDataType* input, CallbackType& callback)
{
if (*d == 0xf0)
{
pendingBytes = 0;
pendingDataTime = time;
}
pendingData.ensureSize ((size_t) (pendingBytes + numBytes), false);
uint8* totalMessage = static_cast<uint8*> (pendingData.getData());
uint8* dest = totalMessage + pendingBytes;
do
{
if (pendingBytes > 0 && *d >= 0x80)
{
if (*d >= 0xfa || *d == 0xf8)
{
callback.handleIncomingMidiMessage (input, MidiMessage (*d, time));
++d;
--numBytes;
}
else
{
if (*d == 0xf7)
{
*dest++ = *d++;
pendingBytes++;
--numBytes;
}
break;
}
}
else
{
*dest++ = *d++;
pendingBytes++;
--numBytes;
}
}
while (numBytes > 0);
if (pendingBytes > 0)
{
if (totalMessage [pendingBytes - 1] == 0xf7)
{
callback.handleIncomingMidiMessage (input, MidiMessage (totalMessage, pendingBytes, pendingDataTime));
pendingBytes = 0;
}
else
{
callback.handlePartialSysexMessage (input, totalMessage, pendingBytes, pendingDataTime);
}
}
}
MemoryBlock pendingData;
double pendingDataTime;
int pendingBytes;
uint8 runningStatus;
JUCE_DECLARE_NON_COPYABLE (MidiDataConcatenator)
};
#endif // __JUCE_MIDIDATACONCATENATOR_JUCEHEADER__

+ 444
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Audio.cpp View File

@@ -0,0 +1,444 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
//==============================================================================
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
STATICMETHOD (getMinBufferSize, "getMinBufferSize", "(III)I") \
STATICMETHOD (getNativeOutputSampleRate, "getNativeOutputSampleRate", "(I)I") \
METHOD (constructor, "<init>", "(IIIIII)V") \
METHOD (getState, "getState", "()I") \
METHOD (play, "play", "()V") \
METHOD (stop, "stop", "()V") \
METHOD (release, "release", "()V") \
METHOD (flush, "flush", "()V") \
METHOD (write, "write", "([SII)I") \
DECLARE_JNI_CLASS (AudioTrack, "android/media/AudioTrack");
#undef JNI_CLASS_MEMBERS
//==============================================================================
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
STATICMETHOD (getMinBufferSize, "getMinBufferSize", "(III)I") \
METHOD (constructor, "<init>", "(IIIII)V") \
METHOD (getState, "getState", "()I") \
METHOD (startRecording, "startRecording", "()V") \
METHOD (stop, "stop", "()V") \
METHOD (read, "read", "([SII)I") \
METHOD (release, "release", "()V") \
DECLARE_JNI_CLASS (AudioRecord, "android/media/AudioRecord");
#undef JNI_CLASS_MEMBERS
//==============================================================================
enum
{
CHANNEL_OUT_STEREO = 12,
CHANNEL_IN_STEREO = 12,
CHANNEL_IN_MONO = 16,
ENCODING_PCM_16BIT = 2,
STREAM_MUSIC = 3,
MODE_STREAM = 1,
STATE_UNINITIALIZED = 0
};
const char* const javaAudioTypeName = "Android Audio";
//==============================================================================
class AndroidAudioIODevice : public AudioIODevice,
public Thread
{
public:
//==============================================================================
AndroidAudioIODevice (const String& deviceName)
: AudioIODevice (deviceName, javaAudioTypeName),
Thread ("audio"),
minBufferSizeOut (0), minBufferSizeIn (0), callback (0), sampleRate (0),
numClientInputChannels (0), numDeviceInputChannels (0), numDeviceInputChannelsAvailable (2),
numClientOutputChannels (0), numDeviceOutputChannels (0),
actualBufferSize (0), isRunning (false),
outputChannelBuffer (1, 1),
inputChannelBuffer (1, 1)
{
JNIEnv* env = getEnv();
sampleRate = env->CallStaticIntMethod (AudioTrack, AudioTrack.getNativeOutputSampleRate, MODE_STREAM);
minBufferSizeOut = (int) env->CallStaticIntMethod (AudioTrack, AudioTrack.getMinBufferSize, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT);
minBufferSizeIn = (int) env->CallStaticIntMethod (AudioRecord, AudioRecord.getMinBufferSize, sampleRate, CHANNEL_IN_STEREO, ENCODING_PCM_16BIT);
if (minBufferSizeIn <= 0)
{
minBufferSizeIn = env->CallStaticIntMethod (AudioRecord, AudioRecord.getMinBufferSize, sampleRate, CHANNEL_IN_MONO, ENCODING_PCM_16BIT);
if (minBufferSizeIn > 0)
numDeviceInputChannelsAvailable = 1;
else
numDeviceInputChannelsAvailable = 0;
}
DBG ("Audio device - min buffers: " << minBufferSizeOut << ", " << minBufferSizeIn << "; "
<< sampleRate << " Hz; input chans: " << numDeviceInputChannelsAvailable);
}
~AndroidAudioIODevice()
{
close();
}
StringArray getOutputChannelNames()
{
StringArray s;
s.add ("Left");
s.add ("Right");
return s;
}
StringArray getInputChannelNames()
{
StringArray s;
if (numDeviceInputChannelsAvailable == 2)
{
s.add ("Left");
s.add ("Right");
}
else if (numDeviceInputChannelsAvailable == 1)
{
s.add ("Audio Input");
}
return s;
}
int getNumSampleRates() { return 1;}
double getSampleRate (int index) { return sampleRate; }
int getDefaultBufferSize() { return 2048; }
int getNumBufferSizesAvailable() { return 50; }
int getBufferSizeSamples (int index)
{
int n = 16;
for (int i = 0; i < index; ++i)
n += n < 64 ? 16
: (n < 512 ? 32
: (n < 1024 ? 64
: (n < 2048 ? 128 : 256)));
return n;
}
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double requestedSampleRate,
int bufferSize)
{
close();
if (sampleRate != (int) requestedSampleRate)
return "Sample rate not allowed";
lastError = String::empty;
int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
numDeviceInputChannels = 0;
numDeviceOutputChannels = 0;
activeOutputChans = outputChannels;
activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false);
numClientOutputChannels = activeOutputChans.countNumberOfSetBits();
activeInputChans = inputChannels;
activeInputChans.setRange (2, activeInputChans.getHighestBit(), false);
numClientInputChannels = activeInputChans.countNumberOfSetBits();
actualBufferSize = preferredBufferSize;
inputChannelBuffer.setSize (2, actualBufferSize);
inputChannelBuffer.clear();
outputChannelBuffer.setSize (2, actualBufferSize);
outputChannelBuffer.clear();
JNIEnv* env = getEnv();
if (numClientOutputChannels > 0)
{
numDeviceOutputChannels = 2;
outputDevice = GlobalRef (env->NewObject (AudioTrack, AudioTrack.constructor,
STREAM_MUSIC, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT,
(jint) (minBufferSizeOut * numDeviceOutputChannels * sizeof (int16)), MODE_STREAM));
if (env->CallIntMethod (outputDevice, AudioTrack.getState) != STATE_UNINITIALIZED)
isRunning = true;
else
outputDevice.clear(); // failed to open the device
}
if (numClientInputChannels > 0 && numDeviceInputChannelsAvailable > 0)
{
numDeviceInputChannels = jmin (numClientInputChannels, numDeviceInputChannelsAvailable);
inputDevice = GlobalRef (env->NewObject (AudioRecord, AudioRecord.constructor,
0 /* (default audio source) */, sampleRate,
numDeviceInputChannelsAvailable > 1 ? CHANNEL_IN_STEREO : CHANNEL_IN_MONO,
ENCODING_PCM_16BIT,
(jint) (minBufferSizeIn * numDeviceInputChannels * sizeof (int16))));
if (env->CallIntMethod (inputDevice, AudioRecord.getState) != STATE_UNINITIALIZED)
isRunning = true;
else
inputDevice.clear(); // failed to open the device
}
if (isRunning)
{
if (outputDevice != nullptr)
env->CallVoidMethod (outputDevice, AudioTrack.play);
if (inputDevice != nullptr)
env->CallVoidMethod (inputDevice, AudioRecord.startRecording);
startThread (8);
}
else
{
closeDevices();
}
return lastError;
}
void close()
{
if (isRunning)
{
stopThread (2000);
isRunning = false;
closeDevices();
}
}
int getOutputLatencyInSamples() { return (minBufferSizeOut * 3) / 4; }
int getInputLatencyInSamples() { return (minBufferSizeIn * 3) / 4; }
bool isOpen() { return isRunning; }
int getCurrentBufferSizeSamples() { return actualBufferSize; }
int getCurrentBitDepth() { return 16; }
double getCurrentSampleRate() { return sampleRate; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; }
BigInteger getActiveInputChannels() const { return activeInputChans; }
String getLastError() { return lastError; }
bool isPlaying() { return isRunning && callback != 0; }
void start (AudioIODeviceCallback* newCallback)
{
if (isRunning && callback != newCallback)
{
if (newCallback != nullptr)
newCallback->audioDeviceAboutToStart (this);
const ScopedLock sl (callbackLock);
callback = newCallback;
}
}
void stop()
{
if (isRunning)
{
AudioIODeviceCallback* lastCallback;
{
const ScopedLock sl (callbackLock);
lastCallback = callback;
callback = nullptr;
}
if (lastCallback != nullptr)
lastCallback->audioDeviceStopped();
}
}
void run()
{
JNIEnv* env = getEnv();
jshortArray audioBuffer = env->NewShortArray (actualBufferSize * jmax (numDeviceOutputChannels, numDeviceInputChannels));
while (! threadShouldExit())
{
if (inputDevice != nullptr)
{
jint numRead = env->CallIntMethod (inputDevice, AudioRecord.read, audioBuffer, 0, actualBufferSize * numDeviceInputChannels);
if (numRead < actualBufferSize * numDeviceInputChannels)
{
DBG ("Audio read under-run! " << numRead);
}
jshort* const src = env->GetShortArrayElements (audioBuffer, 0);
for (int chan = 0; chan < inputChannelBuffer.getNumChannels(); ++chan)
{
AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> d (inputChannelBuffer.getSampleData (chan));
if (chan < numDeviceInputChannels)
{
AudioData::Pointer <AudioData::Int16, AudioData::NativeEndian, AudioData::Interleaved, AudioData::Const> s (src + chan, numDeviceInputChannels);
d.convertSamples (s, actualBufferSize);
}
else
{
d.clearSamples (actualBufferSize);
}
}
env->ReleaseShortArrayElements (audioBuffer, src, 0);
}
if (threadShouldExit())
break;
{
const ScopedLock sl (callbackLock);
if (callback != nullptr)
{
callback->audioDeviceIOCallback ((const float**) inputChannelBuffer.getArrayOfChannels(), numClientInputChannels,
outputChannelBuffer.getArrayOfChannels(), numClientOutputChannels,
actualBufferSize);
}
else
{
outputChannelBuffer.clear();
}
}
if (outputDevice != nullptr)
{
if (threadShouldExit())
break;
jshort* const dest = env->GetShortArrayElements (audioBuffer, 0);
for (int chan = 0; chan < numDeviceOutputChannels; ++chan)
{
AudioData::Pointer <AudioData::Int16, AudioData::NativeEndian, AudioData::Interleaved, AudioData::NonConst> d (dest + chan, numDeviceOutputChannels);
const float* const sourceChanData = outputChannelBuffer.getSampleData (jmin (chan, outputChannelBuffer.getNumChannels() - 1));
AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> s (sourceChanData);
d.convertSamples (s, actualBufferSize);
}
env->ReleaseShortArrayElements (audioBuffer, dest, 0);
jint numWritten = env->CallIntMethod (outputDevice, AudioTrack.write, audioBuffer, 0, actualBufferSize * numDeviceOutputChannels);
if (numWritten < actualBufferSize * numDeviceOutputChannels)
{
DBG ("Audio write underrun! " << numWritten);
}
}
}
}
int minBufferSizeOut, minBufferSizeIn;
private:
//==================================================================================================
CriticalSection callbackLock;
AudioIODeviceCallback* callback;
jint sampleRate;
int numClientInputChannels, numDeviceInputChannels, numDeviceInputChannelsAvailable;
int numClientOutputChannels, numDeviceOutputChannels;
int actualBufferSize;
bool isRunning;
String lastError;
BigInteger activeOutputChans, activeInputChans;
GlobalRef outputDevice, inputDevice;
AudioSampleBuffer inputChannelBuffer, outputChannelBuffer;
void closeDevices()
{
if (outputDevice != nullptr)
{
outputDevice.callVoidMethod (AudioTrack.stop);
outputDevice.callVoidMethod (AudioTrack.release);
outputDevice.clear();
}
if (inputDevice != nullptr)
{
inputDevice.callVoidMethod (AudioRecord.stop);
inputDevice.callVoidMethod (AudioRecord.release);
inputDevice.clear();
}
}
JUCE_DECLARE_NON_COPYABLE (AndroidAudioIODevice)
};
//==============================================================================
class AndroidAudioIODeviceType : public AudioIODeviceType
{
public:
AndroidAudioIODeviceType() : AudioIODeviceType (javaAudioTypeName) {}
//==============================================================================
void scanForDevices() {}
StringArray getDeviceNames (bool wantInputNames) const { return StringArray (javaAudioTypeName); }
int getDefaultDeviceIndex (bool forInput) const { return 0; }
int getIndexOfDevice (AudioIODevice* device, bool asInput) const { return device != nullptr ? 0 : -1; }
bool hasSeparateInputsAndOutputs() const { return false; }
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
ScopedPointer<AndroidAudioIODevice> dev;
if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty())
{
dev = new AndroidAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName);
if (dev->getCurrentSampleRate() <= 0 || dev->getDefaultBufferSize() <= 0)
dev = nullptr;
}
return dev.release();
}
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AndroidAudioIODeviceType)
};
//==============================================================================
extern bool isOpenSLAvailable();
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_Android()
{
#if JUCE_USE_ANDROID_OPENSLES
if (isOpenSLAvailable())
return nullptr;
#endif
return new AndroidAudioIODeviceType();
}

+ 85
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Midi.cpp View File

@@ -0,0 +1,85 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
StringArray MidiOutput::getDevices()
{
StringArray devices;
return devices;
}
int MidiOutput::getDefaultDeviceIndex()
{
return 0;
}
MidiOutput* MidiOutput::openDevice (int index)
{
return nullptr;
}
MidiOutput::~MidiOutput()
{
}
void MidiOutput::sendMessageNow (const MidiMessage&)
{
}
//==============================================================================
MidiInput::MidiInput (const String& name_)
: name (name_),
internal (0)
{
}
MidiInput::~MidiInput()
{
}
void MidiInput::start()
{
}
void MidiInput::stop()
{
}
int MidiInput::getDefaultDeviceIndex()
{
return 0;
}
StringArray MidiInput::getDevices()
{
StringArray devs;
return devs;
}
MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback)
{
return nullptr;
}

+ 623
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp View File

@@ -0,0 +1,623 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
const char* const openSLTypeName = "Android OpenSL";
bool isOpenSLAvailable()
{
DynamicLibrary library;
return library.open ("libOpenSLES.so");
}
const unsigned short openSLRates[] = { 8000, 16000, 32000, 44100, 48000 };
const unsigned short openSLBufferSizes[] = { 256, 512, 768, 1024, 1280, 1600 }; // must all be multiples of the block size
//==============================================================================
class OpenSLAudioIODevice : public AudioIODevice,
public Thread
{
public:
OpenSLAudioIODevice (const String& deviceName)
: AudioIODevice (deviceName, openSLTypeName),
Thread ("OpenSL"),
callback (nullptr), sampleRate (0), deviceOpen (false),
inputBuffer (2, 2), outputBuffer (2, 2)
{
// OpenSL has piss-poor support for determining latency, so the only way I can find to
// get a number for this is by asking the AudioTrack/AudioRecord classes..
AndroidAudioIODevice javaDevice (String::empty);
// this is a total guess about how to calculate the latency, but seems to vaguely agree
// with the devices I've tested.. YMMV
inputLatency = ((javaDevice.minBufferSizeIn * 2) / 3);
outputLatency = ((javaDevice.minBufferSizeOut * 2) / 3);
const int longestLatency = jmax (inputLatency, outputLatency);
const int totalLatency = inputLatency + outputLatency;
inputLatency = ((longestLatency * inputLatency) / totalLatency) & ~15;
outputLatency = ((longestLatency * outputLatency) / totalLatency) & ~15;
}
~OpenSLAudioIODevice()
{
close();
}
bool openedOk() const { return engine.outputMixObject != nullptr; }
StringArray getOutputChannelNames()
{
StringArray s;
s.add ("Left");
s.add ("Right");
return s;
}
StringArray getInputChannelNames()
{
StringArray s;
s.add ("Audio Input");
return s;
}
int getNumSampleRates() { return numElementsInArray (openSLRates); }
double getSampleRate (int index)
{
jassert (index >= 0 && index < getNumSampleRates());
return (int) openSLRates [index];
}
int getDefaultBufferSize() { return 1024; }
int getNumBufferSizesAvailable() { return numElementsInArray (openSLBufferSizes); }
int getBufferSizeSamples (int index)
{
jassert (index >= 0 && index < getNumBufferSizesAvailable());
return (int) openSLBufferSizes [index];
}
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double requestedSampleRate,
int bufferSize)
{
close();
lastError = String::empty;
sampleRate = (int) requestedSampleRate;
int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
activeOutputChans = outputChannels;
activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false);
numOutputChannels = activeOutputChans.countNumberOfSetBits();
activeInputChans = inputChannels;
activeInputChans.setRange (1, activeInputChans.getHighestBit(), false);
numInputChannels = activeInputChans.countNumberOfSetBits();
actualBufferSize = preferredBufferSize;
inputBuffer.setSize (jmax (1, numInputChannels), actualBufferSize);
outputBuffer.setSize (jmax (1, numOutputChannels), actualBufferSize);
outputBuffer.clear();
recorder = engine.createRecorder (numInputChannels, sampleRate);
player = engine.createPlayer (numOutputChannels, sampleRate);
startThread (8);
deviceOpen = true;
return lastError;
}
void close()
{
stop();
stopThread (6000);
deviceOpen = false;
recorder = nullptr;
player = nullptr;
}
int getOutputLatencyInSamples() { return outputLatency; }
int getInputLatencyInSamples() { return inputLatency; }
bool isOpen() { return deviceOpen; }
int getCurrentBufferSizeSamples() { return actualBufferSize; }
int getCurrentBitDepth() { return 16; }
double getCurrentSampleRate() { return sampleRate; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; }
BigInteger getActiveInputChannels() const { return activeInputChans; }
String getLastError() { return lastError; }
bool isPlaying() { return callback != nullptr; }
void start (AudioIODeviceCallback* newCallback)
{
stop();
if (deviceOpen && callback != newCallback)
{
if (newCallback != nullptr)
newCallback->audioDeviceAboutToStart (this);
setCallback (newCallback);
}
}
void stop()
{
if (AudioIODeviceCallback* const oldCallback = setCallback (nullptr))
oldCallback->audioDeviceStopped();
}
void run()
{
if (recorder != nullptr) recorder->start();
if (player != nullptr) player->start();
while (! threadShouldExit())
{
if (player != nullptr) player->writeBuffer (outputBuffer, *this);
if (recorder != nullptr) recorder->readNextBlock (inputBuffer, *this);
const ScopedLock sl (callbackLock);
if (callback != nullptr)
{
callback->audioDeviceIOCallback (numInputChannels > 0 ? (const float**) inputBuffer.getArrayOfChannels() : nullptr,
numInputChannels,
numOutputChannels > 0 ? outputBuffer.getArrayOfChannels() : nullptr,
numOutputChannels,
actualBufferSize);
}
else
{
outputBuffer.clear();
}
}
}
private:
//==================================================================================================
CriticalSection callbackLock;
AudioIODeviceCallback* callback;
int actualBufferSize, sampleRate;
int inputLatency, outputLatency;
bool deviceOpen;
String lastError;
BigInteger activeOutputChans, activeInputChans;
int numInputChannels, numOutputChannels;
AudioSampleBuffer inputBuffer, outputBuffer;
struct Player;
struct Recorder;
AudioIODeviceCallback* setCallback (AudioIODeviceCallback* const newCallback)
{
const ScopedLock sl (callbackLock);
AudioIODeviceCallback* const oldCallback = callback;
callback = newCallback;
return oldCallback;
}
//==================================================================================================
struct Engine
{
Engine()
: engineObject (nullptr), engineInterface (nullptr), outputMixObject (nullptr)
{
if (library.open ("libOpenSLES.so"))
{
typedef SLresult (*CreateEngineFunc) (SLObjectItf*, SLuint32, const SLEngineOption*, SLuint32, const SLInterfaceID*, const SLboolean*);
if (CreateEngineFunc createEngine = (CreateEngineFunc) library.getFunction ("slCreateEngine"))
{
check (createEngine (&engineObject, 0, nullptr, 0, nullptr, nullptr));
SLInterfaceID* SL_IID_ENGINE = (SLInterfaceID*) library.getFunction ("SL_IID_ENGINE");
SL_IID_ANDROIDSIMPLEBUFFERQUEUE = (SLInterfaceID*) library.getFunction ("SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
SL_IID_PLAY = (SLInterfaceID*) library.getFunction ("SL_IID_PLAY");
SL_IID_RECORD = (SLInterfaceID*) library.getFunction ("SL_IID_RECORD");
check ((*engineObject)->Realize (engineObject, SL_BOOLEAN_FALSE));
check ((*engineObject)->GetInterface (engineObject, *SL_IID_ENGINE, &engineInterface));
check ((*engineInterface)->CreateOutputMix (engineInterface, &outputMixObject, 0, nullptr, nullptr));
check ((*outputMixObject)->Realize (outputMixObject, SL_BOOLEAN_FALSE));
}
}
}
~Engine()
{
if (outputMixObject != nullptr) (*outputMixObject)->Destroy (outputMixObject);
if (engineObject != nullptr) (*engineObject)->Destroy (engineObject);
}
Player* createPlayer (const int numChannels, const int sampleRate)
{
if (numChannels <= 0)
return nullptr;
ScopedPointer<Player> player (new Player (numChannels, sampleRate, *this));
return player->openedOk() ? player.release() : nullptr;
}
Recorder* createRecorder (const int numChannels, const int sampleRate)
{
if (numChannels <= 0)
return nullptr;
ScopedPointer<Recorder> recorder (new Recorder (numChannels, sampleRate, *this));
return recorder->openedOk() ? recorder.release() : nullptr;
}
SLObjectItf engineObject;
SLEngineItf engineInterface;
SLObjectItf outputMixObject;
SLInterfaceID* SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
SLInterfaceID* SL_IID_PLAY;
SLInterfaceID* SL_IID_RECORD;
private:
DynamicLibrary library;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Engine)
};
//==================================================================================================
struct BufferList
{
BufferList (const int numChannels_)
: numChannels (numChannels_), bufferSpace (numChannels_ * numSamples * numBuffers), nextBlock (0)
{
}
int16* waitForFreeBuffer (Thread& threadToCheck)
{
while (numBlocksOut.get() == numBuffers)
{
dataArrived.wait (1);
if (threadToCheck.threadShouldExit())
return nullptr;
}
return getNextBuffer();
}
int16* getNextBuffer()
{
if (++nextBlock == numBuffers)
nextBlock = 0;
return bufferSpace + nextBlock * numChannels * numSamples;
}
void bufferReturned() { --numBlocksOut; dataArrived.signal(); }
void bufferSent() { ++numBlocksOut; dataArrived.signal(); }
int getBufferSizeBytes() const { return numChannels * numSamples * sizeof (int16); }
const int numChannels;
enum { numSamples = 256, numBuffers = 16 };
private:
HeapBlock<int16> bufferSpace;
int nextBlock;
Atomic<int> numBlocksOut;
WaitableEvent dataArrived;
};
//==================================================================================================
struct Player
{
Player (int numChannels, int sampleRate, Engine& engine)
: playerObject (nullptr), playerPlay (nullptr), playerBufferQueue (nullptr),
bufferList (numChannels)
{
jassert (numChannels == 2);
SLDataFormat_PCM pcmFormat =
{
SL_DATAFORMAT_PCM,
numChannels,
sampleRate * 1000, // (sample rate units are millihertz)
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN
};
SLDataLocator_AndroidSimpleBufferQueue bufferQueue = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, bufferList.numBuffers };
SLDataSource audioSrc = { &bufferQueue, &pcmFormat };
SLDataLocator_OutputMix outputMix = { SL_DATALOCATOR_OUTPUTMIX, engine.outputMixObject };
SLDataSink audioSink = { &outputMix, nullptr };
// (SL_IID_BUFFERQUEUE is not guaranteed to remain future-proof, so use SL_IID_ANDROIDSIMPLEBUFFERQUEUE)
const SLInterfaceID interfaceIDs[] = { *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE };
const SLboolean flags[] = { SL_BOOLEAN_TRUE };
check ((*engine.engineInterface)->CreateAudioPlayer (engine.engineInterface, &playerObject, &audioSrc, &audioSink,
1, interfaceIDs, flags));
check ((*playerObject)->Realize (playerObject, SL_BOOLEAN_FALSE));
check ((*playerObject)->GetInterface (playerObject, *engine.SL_IID_PLAY, &playerPlay));
check ((*playerObject)->GetInterface (playerObject, *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &playerBufferQueue));
check ((*playerBufferQueue)->RegisterCallback (playerBufferQueue, staticCallback, this));
}
~Player()
{
if (playerPlay != nullptr)
check ((*playerPlay)->SetPlayState (playerPlay, SL_PLAYSTATE_STOPPED));
if (playerBufferQueue != nullptr)
check ((*playerBufferQueue)->Clear (playerBufferQueue));
if (playerObject != nullptr)
(*playerObject)->Destroy (playerObject);
}
bool openedOk() const noexcept { return playerBufferQueue != nullptr; }
void start()
{
jassert (openedOk());
check ((*playerPlay)->SetPlayState (playerPlay, SL_PLAYSTATE_PLAYING));
}
void writeBuffer (const AudioSampleBuffer& buffer, Thread& thread)
{
jassert (buffer.getNumChannels() == bufferList.numChannels);
jassert (buffer.getNumSamples() < bufferList.numSamples * bufferList.numBuffers);
int offset = 0;
int numSamples = buffer.getNumSamples();
while (numSamples > 0)
{
int16* const destBuffer = bufferList.waitForFreeBuffer (thread);
if (destBuffer == nullptr)
break;
for (int i = 0; i < bufferList.numChannels; ++i)
{
typedef AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> DstSampleType;
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SrcSampleType;
DstSampleType dstData (destBuffer + i, bufferList.numChannels);
SrcSampleType srcData (buffer.getSampleData (i, offset));
dstData.convertSamples (srcData, bufferList.numSamples);
}
check ((*playerBufferQueue)->Enqueue (playerBufferQueue, destBuffer, bufferList.getBufferSizeBytes()));
bufferList.bufferSent();
numSamples -= bufferList.numSamples;
offset += bufferList.numSamples;
}
}
private:
SLObjectItf playerObject;
SLPlayItf playerPlay;
SLAndroidSimpleBufferQueueItf playerBufferQueue;
BufferList bufferList;
static void staticCallback (SLAndroidSimpleBufferQueueItf queue, void* context)
{
jassert (queue == static_cast <Player*> (context)->playerBufferQueue); (void) queue;
static_cast <Player*> (context)->bufferList.bufferReturned();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Player)
};
//==================================================================================================
struct Recorder
{
Recorder (int numChannels, int sampleRate, Engine& engine)
: recorderObject (nullptr), recorderRecord (nullptr), recorderBufferQueue (nullptr),
bufferList (numChannels)
{
jassert (numChannels == 1); // STEREO doesn't always work!!
SLDataFormat_PCM pcmFormat =
{
SL_DATAFORMAT_PCM,
numChannels,
sampleRate * 1000, // (sample rate units are millihertz)
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
(numChannels == 1) ? SL_SPEAKER_FRONT_CENTER : (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT),
SL_BYTEORDER_LITTLEENDIAN
};
SLDataLocator_IODevice ioDevice = { SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, nullptr };
SLDataSource audioSrc = { &ioDevice, nullptr };
SLDataLocator_AndroidSimpleBufferQueue bufferQueue = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, bufferList.numBuffers };
SLDataSink audioSink = { &bufferQueue, &pcmFormat };
const SLInterfaceID interfaceIDs[] = { *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE };
const SLboolean flags[] = { SL_BOOLEAN_TRUE };
if (check ((*engine.engineInterface)->CreateAudioRecorder (engine.engineInterface, &recorderObject, &audioSrc,
&audioSink, 1, interfaceIDs, flags)))
{
if (check ((*recorderObject)->Realize (recorderObject, SL_BOOLEAN_FALSE)))
{
check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_RECORD, &recorderRecord));
check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue));
check ((*recorderBufferQueue)->RegisterCallback (recorderBufferQueue, staticCallback, this));
check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_STOPPED));
for (int i = bufferList.numBuffers; --i >= 0;)
{
int16* const buffer = bufferList.getNextBuffer();
jassert (buffer != nullptr);
enqueueBuffer (buffer);
}
}
}
}
~Recorder()
{
if (recorderRecord != nullptr)
check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_STOPPED));
if (recorderBufferQueue != nullptr)
check ((*recorderBufferQueue)->Clear (recorderBufferQueue));
if (recorderObject != nullptr)
(*recorderObject)->Destroy (recorderObject);
}
bool openedOk() const noexcept { return recorderBufferQueue != nullptr; }
void start()
{
jassert (openedOk());
check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_RECORDING));
}
void readNextBlock (AudioSampleBuffer& buffer, Thread& thread)
{
jassert (buffer.getNumChannels() == bufferList.numChannels);
jassert (buffer.getNumSamples() < bufferList.numSamples * bufferList.numBuffers);
jassert ((buffer.getNumSamples() % bufferList.numSamples) == 0);
int offset = 0;
int numSamples = buffer.getNumSamples();
while (numSamples > 0)
{
int16* const srcBuffer = bufferList.waitForFreeBuffer (thread);
if (srcBuffer == nullptr)
break;
for (int i = 0; i < bufferList.numChannels; ++i)
{
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DstSampleType;
typedef AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const> SrcSampleType;
DstSampleType dstData (buffer.getSampleData (i, offset));
SrcSampleType srcData (srcBuffer + i, bufferList.numChannels);
dstData.convertSamples (srcData, bufferList.numSamples);
}
enqueueBuffer (srcBuffer);
numSamples -= bufferList.numSamples;
offset += bufferList.numSamples;
}
}
private:
SLObjectItf recorderObject;
SLRecordItf recorderRecord;
SLAndroidSimpleBufferQueueItf recorderBufferQueue;
BufferList bufferList;
void enqueueBuffer (int16* buffer)
{
check ((*recorderBufferQueue)->Enqueue (recorderBufferQueue, buffer, bufferList.getBufferSizeBytes()));
bufferList.bufferSent();
}
static void staticCallback (SLAndroidSimpleBufferQueueItf queue, void* context)
{
jassert (queue == static_cast <Recorder*> (context)->recorderBufferQueue); (void) queue;
static_cast <Recorder*> (context)->bufferList.bufferReturned();
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Recorder)
};
//==============================================================================
Engine engine;
ScopedPointer<Player> player;
ScopedPointer<Recorder> recorder;
//==============================================================================
static bool check (const SLresult result)
{
jassert (result == SL_RESULT_SUCCESS);
return result == SL_RESULT_SUCCESS;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenSLAudioIODevice)
};
//==============================================================================
class OpenSLAudioDeviceType : public AudioIODeviceType
{
public:
OpenSLAudioDeviceType() : AudioIODeviceType (openSLTypeName) {}
//==============================================================================
void scanForDevices() {}
StringArray getDeviceNames (bool wantInputNames) const { return StringArray (openSLTypeName); }
int getDefaultDeviceIndex (bool forInput) const { return 0; }
int getIndexOfDevice (AudioIODevice* device, bool asInput) const { return device != nullptr ? 0 : -1; }
bool hasSeparateInputsAndOutputs() const { return false; }
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
ScopedPointer<OpenSLAudioIODevice> dev;
if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty())
{
dev = new OpenSLAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName);
if (! dev->openedOk())
dev = nullptr;
}
return dev.release();
}
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenSLAudioDeviceType)
};
//==============================================================================
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_OpenSLES()
{
return isOpenSLAvailable() ? new OpenSLAudioDeviceType() : nullptr;
}

+ 547
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp View File

@@ -0,0 +1,547 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
class iOSAudioIODevice : public AudioIODevice
{
public:
iOSAudioIODevice (const String& deviceName)
: AudioIODevice (deviceName, "Audio"),
actualBufferSize (0),
isRunning (false),
audioUnit (0),
callback (nullptr),
floatData (1, 2)
{
getSessionHolder().activeDevices.add (this);
numInputChannels = 2;
numOutputChannels = 2;
preferredBufferSize = 0;
updateDeviceInfo();
}
~iOSAudioIODevice()
{
getSessionHolder().activeDevices.removeFirstMatchingValue (this);
close();
}
StringArray getOutputChannelNames()
{
StringArray s;
s.add ("Left");
s.add ("Right");
return s;
}
StringArray getInputChannelNames()
{
StringArray s;
if (audioInputIsAvailable)
{
s.add ("Left");
s.add ("Right");
}
return s;
}
int getNumSampleRates() { return 1; }
double getSampleRate (int index) { return sampleRate; }
int getNumBufferSizesAvailable() { return 6; }
int getBufferSizeSamples (int index) { return 1 << (jlimit (0, 5, index) + 6); }
int getDefaultBufferSize() { return 1024; }
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double sampleRate,
int bufferSize)
{
close();
lastError = String::empty;
preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
// xxx set up channel mapping
activeOutputChans = outputChannels;
activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false);
numOutputChannels = activeOutputChans.countNumberOfSetBits();
monoOutputChannelNumber = activeOutputChans.findNextSetBit (0);
activeInputChans = inputChannels;
activeInputChans.setRange (2, activeInputChans.getHighestBit(), false);
numInputChannels = activeInputChans.countNumberOfSetBits();
monoInputChannelNumber = activeInputChans.findNextSetBit (0);
AudioSessionSetActive (true);
UInt32 audioCategory = kAudioSessionCategory_MediaPlayback;
if (numInputChannels > 0 && audioInputIsAvailable)
{
audioCategory = kAudioSessionCategory_PlayAndRecord;
UInt32 allowBluetoothInput = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof (allowBluetoothInput), &allowBluetoothInput);
}
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (audioCategory), &audioCategory);
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, routingChangedStatic, this);
fixAudioRouteIfSetToReceiver();
updateDeviceInfo();
Float32 bufferDuration = preferredBufferSize / sampleRate;
AudioSessionSetProperty (kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof (bufferDuration), &bufferDuration);
actualBufferSize = preferredBufferSize;
prepareFloatBuffers();
isRunning = true;
routingChanged (nullptr); // creates and starts the AU
lastError = audioUnit != 0 ? "" : "Couldn't open the device";
return lastError;
}
void close()
{
if (isRunning)
{
isRunning = false;
AudioSessionRemovePropertyListenerWithUserData (kAudioSessionProperty_AudioRouteChange, routingChangedStatic, this);
AudioSessionSetActive (false);
if (audioUnit != 0)
{
AudioComponentInstanceDispose (audioUnit);
audioUnit = 0;
}
}
}
bool isOpen() { return isRunning; }
int getCurrentBufferSizeSamples() { return actualBufferSize; }
double getCurrentSampleRate() { return sampleRate; }
int getCurrentBitDepth() { return 16; }
BigInteger getActiveOutputChannels() const { return activeOutputChans; }
BigInteger getActiveInputChannels() const { return activeInputChans; }
int getOutputLatencyInSamples() { return 0; } //xxx
int getInputLatencyInSamples() { return 0; } //xxx
void start (AudioIODeviceCallback* newCallback)
{
if (isRunning && callback != newCallback)
{
if (newCallback != nullptr)
newCallback->audioDeviceAboutToStart (this);
const ScopedLock sl (callbackLock);
callback = newCallback;
}
}
void stop()
{
if (isRunning)
{
AudioIODeviceCallback* lastCallback;
{
const ScopedLock sl (callbackLock);
lastCallback = callback;
callback = nullptr;
}
if (lastCallback != nullptr)
lastCallback->audioDeviceStopped();
}
}
bool isPlaying() { return isRunning && callback != nullptr; }
String getLastError() { return lastError; }
private:
//==================================================================================================
CriticalSection callbackLock;
Float64 sampleRate;
int numInputChannels, numOutputChannels;
int preferredBufferSize, actualBufferSize;
bool isRunning;
String lastError;
AudioStreamBasicDescription format;
AudioUnit audioUnit;
UInt32 audioInputIsAvailable;
AudioIODeviceCallback* callback;
BigInteger activeOutputChans, activeInputChans;
AudioSampleBuffer floatData;
float* inputChannels[3];
float* outputChannels[3];
bool monoInputChannelNumber, monoOutputChannelNumber;
void prepareFloatBuffers()
{
floatData.setSize (numInputChannels + numOutputChannels, actualBufferSize);
zeromem (inputChannels, sizeof (inputChannels));
zeromem (outputChannels, sizeof (outputChannels));
for (int i = 0; i < numInputChannels; ++i)
inputChannels[i] = floatData.getSampleData (i);
for (int i = 0; i < numOutputChannels; ++i)
outputChannels[i] = floatData.getSampleData (i + numInputChannels);
}
//==================================================================================================
OSStatus process (AudioUnitRenderActionFlags* flags, const AudioTimeStamp* time,
const UInt32 numFrames, AudioBufferList* data)
{
OSStatus err = noErr;
if (audioInputIsAvailable && numInputChannels > 0)
err = AudioUnitRender (audioUnit, flags, time, 1, numFrames, data);
const ScopedLock sl (callbackLock);
if (callback != nullptr)
{
if (audioInputIsAvailable && numInputChannels > 0)
{
short* shortData = (short*) data->mBuffers[0].mData;
if (numInputChannels >= 2)
{
for (UInt32 i = 0; i < numFrames; ++i)
{
inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f);
inputChannels[1][i] = *shortData++ * (1.0f / 32768.0f);
}
}
else
{
if (monoInputChannelNumber > 0)
++shortData;
for (UInt32 i = 0; i < numFrames; ++i)
{
inputChannels[0][i] = *shortData++ * (1.0f / 32768.0f);
++shortData;
}
}
}
else
{
for (int i = numInputChannels; --i >= 0;)
zeromem (inputChannels[i], sizeof (float) * numFrames);
}
callback->audioDeviceIOCallback ((const float**) inputChannels, numInputChannels,
outputChannels, numOutputChannels, (int) numFrames);
short* shortData = (short*) data->mBuffers[0].mData;
int n = 0;
if (numOutputChannels >= 2)
{
for (UInt32 i = 0; i < numFrames; ++i)
{
shortData [n++] = (short) (outputChannels[0][i] * 32767.0f);
shortData [n++] = (short) (outputChannels[1][i] * 32767.0f);
}
}
else if (numOutputChannels == 1)
{
for (UInt32 i = 0; i < numFrames; ++i)
{
const short s = (short) (outputChannels[monoOutputChannelNumber][i] * 32767.0f);
shortData [n++] = s;
shortData [n++] = s;
}
}
else
{
zeromem (data->mBuffers[0].mData, 2 * sizeof (short) * numFrames);
}
}
else
{
zeromem (data->mBuffers[0].mData, 2 * sizeof (short) * numFrames);
}
return err;
}
void updateDeviceInfo()
{
UInt32 size = sizeof (sampleRate);
AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareSampleRate, &size, &sampleRate);
size = sizeof (audioInputIsAvailable);
AudioSessionGetProperty (kAudioSessionProperty_AudioInputAvailable, &size, &audioInputIsAvailable);
}
void routingChanged (const void* propertyValue)
{
if (! isRunning)
return;
if (propertyValue != nullptr)
{
CFDictionaryRef routeChangeDictionary = (CFDictionaryRef) propertyValue;
CFNumberRef routeChangeReasonRef = (CFNumberRef) CFDictionaryGetValue (routeChangeDictionary,
CFSTR (kAudioSession_AudioRouteChangeKey_Reason));
SInt32 routeChangeReason;
CFNumberGetValue (routeChangeReasonRef, kCFNumberSInt32Type, &routeChangeReason);
if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable)
{
const ScopedLock sl (callbackLock);
if (callback != nullptr)
callback->audioDeviceError ("Old device unavailable");
}
}
updateDeviceInfo();
createAudioUnit();
AudioSessionSetActive (true);
if (audioUnit != 0)
{
UInt32 formatSize = sizeof (format);
AudioUnitGetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, &formatSize);
Float32 bufferDuration = preferredBufferSize / sampleRate;
UInt32 bufferDurationSize = sizeof (bufferDuration);
AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareIOBufferDuration, &bufferDurationSize, &bufferDurationSize);
actualBufferSize = (int) (sampleRate * bufferDuration + 0.5);
AudioOutputUnitStart (audioUnit);
}
}
//==================================================================================================
struct AudioSessionHolder
{
AudioSessionHolder()
{
AudioSessionInitialize (0, 0, interruptionListenerCallback, this);
}
static void interruptionListenerCallback (void* client, UInt32 interruptionType)
{
const Array <iOSAudioIODevice*>& activeDevices = static_cast <AudioSessionHolder*> (client)->activeDevices;
for (int i = activeDevices.size(); --i >= 0;)
activeDevices.getUnchecked(i)->interruptionListener (interruptionType);
}
Array <iOSAudioIODevice*> activeDevices;
};
static AudioSessionHolder& getSessionHolder()
{
static AudioSessionHolder audioSessionHolder;
return audioSessionHolder;
}
void interruptionListener (const UInt32 interruptionType)
{
if (interruptionType == kAudioSessionBeginInterruption)
{
close();
const ScopedLock sl (callbackLock);
if (callback != nullptr)
callback->audioDeviceError ("iOS audio session interruption");
}
if (interruptionType == kAudioSessionEndInterruption)
{
isRunning = true;
AudioSessionSetActive (true);
AudioOutputUnitStart (audioUnit);
}
}
//==================================================================================================
static OSStatus processStatic (void* client, AudioUnitRenderActionFlags* flags, const AudioTimeStamp* time,
UInt32 /*busNumber*/, UInt32 numFrames, AudioBufferList* data)
{
return static_cast <iOSAudioIODevice*> (client)->process (flags, time, numFrames, data);
}
static void routingChangedStatic (void* client, AudioSessionPropertyID, UInt32 /*inDataSize*/, const void* propertyValue)
{
static_cast <iOSAudioIODevice*> (client)->routingChanged (propertyValue);
}
//==================================================================================================
void resetFormat (const int numChannels) noexcept
{
zerostruct (format);
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kAudioFormatFlagsNativeEndian;
format.mBitsPerChannel = 8 * sizeof (short);
format.mChannelsPerFrame = numChannels;
format.mFramesPerPacket = 1;
format.mBytesPerFrame = format.mBytesPerPacket = numChannels * sizeof (short);
}
bool createAudioUnit()
{
if (audioUnit != 0)
{
AudioComponentInstanceDispose (audioUnit);
audioUnit = 0;
}
resetFormat (2);
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
AudioComponent comp = AudioComponentFindNext (0, &desc);
AudioComponentInstanceNew (comp, &audioUnit);
if (audioUnit == 0)
return false;
if (numInputChannels > 0)
{
const UInt32 one = 1;
AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &one, sizeof (one));
}
{
AudioChannelLayout layout;
layout.mChannelBitmap = 0;
layout.mNumberChannelDescriptions = 0;
layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Input, 0, &layout, sizeof (layout));
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output, 0, &layout, sizeof (layout));
}
{
AURenderCallbackStruct inputProc;
inputProc.inputProc = processStatic;
inputProc.inputProcRefCon = this;
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &inputProc, sizeof (inputProc));
}
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof (format));
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, sizeof (format));
AudioUnitInitialize (audioUnit);
return true;
}
// If the routing is set to go through the receiver (i.e. the speaker, but quiet), this re-routes it
// to make it loud. Needed because by default when using an input + output, the output is kept quiet.
static void fixAudioRouteIfSetToReceiver()
{
CFStringRef audioRoute = 0;
UInt32 propertySize = sizeof (audioRoute);
if (AudioSessionGetProperty (kAudioSessionProperty_AudioRoute, &propertySize, &audioRoute) == noErr)
{
NSString* route = (NSString*) audioRoute;
//DBG ("audio route: " + nsStringToJuce (route));
if ([route hasPrefix: @"Receiver"])
{
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride);
}
CFRelease (audioRoute);
}
}
JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice)
};
//==============================================================================
class iOSAudioIODeviceType : public AudioIODeviceType
{
public:
iOSAudioIODeviceType() : AudioIODeviceType ("iOS Audio")
{
}
void scanForDevices() {}
StringArray getDeviceNames (bool wantInputNames) const
{
return StringArray ("iOS Audio");
}
int getDefaultDeviceIndex (bool forInput) const
{
return 0;
}
int getIndexOfDevice (AudioIODevice* device, bool asInput) const
{
return device != nullptr ? 0 : -1;
}
bool hasSeparateInputsAndOutputs() const { return false; }
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty())
return new iOSAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName);
return nullptr;
}
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (iOSAudioIODeviceType)
};
//==============================================================================
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_iOSAudio()
{
return new iOSAudioIODeviceType();
}

+ 1011
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp
File diff suppressed because it is too large
View File


+ 78
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_AudioCDReader.cpp View File

@@ -0,0 +1,78 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
AudioCDReader::AudioCDReader()
: AudioFormatReader (0, "CD Audio")
{
}
StringArray AudioCDReader::getAvailableCDNames()
{
StringArray names;
return names;
}
AudioCDReader* AudioCDReader::createReaderForCD (const int index)
{
return nullptr;
}
AudioCDReader::~AudioCDReader()
{
}
void AudioCDReader::refreshTrackLengths()
{
}
bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
int64 startSampleInFile, int numSamples)
{
return false;
}
bool AudioCDReader::isCDStillPresent() const
{
return false;
}
bool AudioCDReader::isTrackAudio (int trackNum) const
{
return false;
}
void AudioCDReader::enableIndexScanning (bool b)
{
}
int AudioCDReader::getLastIndex() const
{
return 0;
}
Array<int> AudioCDReader::findIndexesInTrack (const int trackNumber)
{
return Array<int>();
}

+ 606
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp View File

@@ -0,0 +1,606 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
//==============================================================================
static void* juce_libjackHandle = nullptr;
static void* juce_loadJackFunction (const char* const name)
{
if (juce_libjackHandle == nullptr)
return nullptr;
return dlsym (juce_libjackHandle, name);
}
#define JUCE_DECL_JACK_FUNCTION(return_type, fn_name, argument_types, arguments) \
return_type fn_name argument_types \
{ \
typedef return_type (*fn_type) argument_types; \
static fn_type fn = (fn_type) juce_loadJackFunction (#fn_name); \
return (fn != nullptr) ? ((*fn) arguments) : (return_type) 0; \
}
#define JUCE_DECL_VOID_JACK_FUNCTION(fn_name, argument_types, arguments) \
void fn_name argument_types \
{ \
typedef void (*fn_type) argument_types; \
static fn_type fn = (fn_type) juce_loadJackFunction (#fn_name); \
if (fn != nullptr) (*fn) arguments; \
}
//==============================================================================
JUCE_DECL_JACK_FUNCTION (jack_client_t*, jack_client_open, (const char* client_name, jack_options_t options, jack_status_t* status, ...), (client_name, options, status));
JUCE_DECL_JACK_FUNCTION (int, jack_client_close, (jack_client_t *client), (client));
JUCE_DECL_JACK_FUNCTION (int, jack_activate, (jack_client_t* client), (client));
JUCE_DECL_JACK_FUNCTION (int, jack_deactivate, (jack_client_t* client), (client));
JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_get_buffer_size, (jack_client_t* client), (client));
JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_get_sample_rate, (jack_client_t* client), (client));
JUCE_DECL_VOID_JACK_FUNCTION (jack_on_shutdown, (jack_client_t* client, void (*function)(void* arg), void* arg), (client, function, arg));
JUCE_DECL_JACK_FUNCTION (void* , jack_port_get_buffer, (jack_port_t* port, jack_nframes_t nframes), (port, nframes));
JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_port_get_total_latency, (jack_client_t* client, jack_port_t* port), (client, port));
JUCE_DECL_JACK_FUNCTION (jack_port_t* , jack_port_register, (jack_client_t* client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size), (client, port_name, port_type, flags, buffer_size));
JUCE_DECL_VOID_JACK_FUNCTION (jack_set_error_function, (void (*func)(const char*)), (func));
JUCE_DECL_JACK_FUNCTION (int, jack_set_process_callback, (jack_client_t* client, JackProcessCallback process_callback, void* arg), (client, process_callback, arg));
JUCE_DECL_JACK_FUNCTION (const char**, jack_get_ports, (jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags), (client, port_name_pattern, type_name_pattern, flags));
JUCE_DECL_JACK_FUNCTION (int, jack_connect, (jack_client_t* client, const char* source_port, const char* destination_port), (client, source_port, destination_port));
JUCE_DECL_JACK_FUNCTION (const char*, jack_port_name, (const jack_port_t* port), (port));
JUCE_DECL_JACK_FUNCTION (void*, jack_set_port_connect_callback, (jack_client_t* client, JackPortConnectCallback connect_callback, void* arg), (client, connect_callback, arg));
JUCE_DECL_JACK_FUNCTION (jack_port_t* , jack_port_by_id, (jack_client_t* client, jack_port_id_t port_id), (client, port_id));
JUCE_DECL_JACK_FUNCTION (int, jack_port_connected, (const jack_port_t* port), (port));
JUCE_DECL_JACK_FUNCTION (int, jack_port_connected_to, (const jack_port_t* port, const char* port_name), (port, port_name));
#if JUCE_DEBUG
#define JACK_LOGGING_ENABLED 1
#endif
#if JACK_LOGGING_ENABLED
namespace
{
void jack_Log (const String& s)
{
std::cerr << s << std::endl;
}
void dumpJackErrorMessage (const jack_status_t status)
{
if (status & JackServerFailed || status & JackServerError) jack_Log ("Unable to connect to JACK server");
if (status & JackVersionError) jack_Log ("Client's protocol version does not match");
if (status & JackInvalidOption) jack_Log ("The operation contained an invalid or unsupported option");
if (status & JackNameNotUnique) jack_Log ("The desired client name was not unique");
if (status & JackNoSuchClient) jack_Log ("Requested client does not exist");
if (status & JackInitFailure) jack_Log ("Unable to initialize client");
}
}
#else
#define dumpJackErrorMessage(a) {}
#define jack_Log(...) {}
#endif
//==============================================================================
#ifndef JUCE_JACK_CLIENT_NAME
#define JUCE_JACK_CLIENT_NAME "JUCEJack"
#endif
static const char** getJackPorts (jack_client_t* const client, const bool forInput)
{
if (client != nullptr)
return juce::jack_get_ports (client, nullptr, nullptr,
forInput ? JackPortIsOutput : JackPortIsInput);
// (NB: This looks like it's the wrong way round, but it is correct!)
return nullptr;
}
class JackAudioIODeviceType;
static Array<JackAudioIODeviceType*> activeDeviceTypes;
//==============================================================================
class JackAudioIODevice : public AudioIODevice
{
public:
JackAudioIODevice (const String& deviceName,
const String& inId,
const String& outId)
: AudioIODevice (deviceName, "JACK"),
inputId (inId),
outputId (outId),
isOpen_ (false),
callback (nullptr),
totalNumberOfInputChannels (0),
totalNumberOfOutputChannels (0)
{
jassert (deviceName.isNotEmpty());
jack_status_t status;
client = juce::jack_client_open (JUCE_JACK_CLIENT_NAME, JackNoStartServer, &status);
if (client == nullptr)
{
dumpJackErrorMessage (status);
}
else
{
juce::jack_set_error_function (errorCallback);
// open input ports
const StringArray inputChannels (getInputChannelNames());
for (int i = 0; i < inputChannels.size(); ++i)
{
String inputName;
inputName << "in_" << ++totalNumberOfInputChannels;
inputPorts.add (juce::jack_port_register (client, inputName.toUTF8(),
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0));
}
// open output ports
const StringArray outputChannels (getOutputChannelNames());
for (int i = 0; i < outputChannels.size (); ++i)
{
String outputName;
outputName << "out_" << ++totalNumberOfOutputChannels;
outputPorts.add (juce::jack_port_register (client, outputName.toUTF8(),
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0));
}
inChans.calloc (totalNumberOfInputChannels + 2);
outChans.calloc (totalNumberOfOutputChannels + 2);
}
}
~JackAudioIODevice()
{
close();
if (client != nullptr)
{
juce::jack_client_close (client);
client = nullptr;
}
}
StringArray getChannelNames (bool forInput) const
{
StringArray names;
if (const char** const ports = getJackPorts (client, forInput))
{
for (int j = 0; ports[j] != nullptr; ++j)
{
const String portName (ports [j]);
if (portName.upToFirstOccurrenceOf (":", false, false) == getName())
names.add (portName.fromFirstOccurrenceOf (":", false, false));
}
free (ports);
}
return names;
}
StringArray getOutputChannelNames() { return getChannelNames (false); }
StringArray getInputChannelNames() { return getChannelNames (true); }
int getNumSampleRates() { return client != nullptr ? 1 : 0; }
double getSampleRate (int /*index*/) { return client != nullptr ? juce::jack_get_sample_rate (client) : 0; }
int getNumBufferSizesAvailable() { return client != nullptr ? 1 : 0; }
int getBufferSizeSamples (int /*index*/) { return getDefaultBufferSize(); }
int getDefaultBufferSize() { return client != nullptr ? juce::jack_get_buffer_size (client) : 0; }
String open (const BigInteger& inputChannels, const BigInteger& outputChannels,
double /* sampleRate */, int /* bufferSizeSamples */)
{
if (client == nullptr)
{
lastError = "No JACK client running";
return lastError;
}
lastError = String::empty;
close();
juce::jack_set_process_callback (client, processCallback, this);
juce::jack_set_port_connect_callback (client, portConnectCallback, this);
juce::jack_on_shutdown (client, shutdownCallback, this);
juce::jack_activate (client);
isOpen_ = true;
if (! inputChannels.isZero())
{
if (const char** const ports = getJackPorts (client, true))
{
const int numInputChannels = inputChannels.getHighestBit() + 1;
for (int i = 0; i < numInputChannels; ++i)
{
const String portName (ports[i]);
if (inputChannels[i] && portName.upToFirstOccurrenceOf (":", false, false) == getName())
{
int error = juce::jack_connect (client, ports[i], juce::jack_port_name ((jack_port_t*) inputPorts[i]));
if (error != 0)
jack_Log ("Cannot connect input port " + String (i) + " (" + String (ports[i]) + "), error " + String (error));
}
}
free (ports);
}
}
if (! outputChannels.isZero())
{
if (const char** const ports = getJackPorts (client, false))
{
const int numOutputChannels = outputChannels.getHighestBit() + 1;
for (int i = 0; i < numOutputChannels; ++i)
{
const String portName (ports[i]);
if (outputChannels[i] && portName.upToFirstOccurrenceOf (":", false, false) == getName())
{
int error = juce::jack_connect (client, juce::jack_port_name ((jack_port_t*) outputPorts[i]), ports[i]);
if (error != 0)
jack_Log ("Cannot connect output port " + String (i) + " (" + String (ports[i]) + "), error " + String (error));
}
}
free (ports);
}
}
return lastError;
}
void close()
{
stop();
if (client != nullptr)
{
juce::jack_deactivate (client);
juce::jack_set_process_callback (client, processCallback, nullptr);
juce::jack_set_port_connect_callback (client, portConnectCallback, nullptr);
juce::jack_on_shutdown (client, shutdownCallback, nullptr);
}
isOpen_ = false;
}
void start (AudioIODeviceCallback* newCallback)
{
if (isOpen_ && newCallback != callback)
{
if (newCallback != nullptr)
newCallback->audioDeviceAboutToStart (this);
AudioIODeviceCallback* const oldCallback = callback;
{
const ScopedLock sl (callbackLock);
callback = newCallback;
}
if (oldCallback != nullptr)
oldCallback->audioDeviceStopped();
}
}
void stop()
{
start (nullptr);
}
bool isOpen() { return isOpen_; }
bool isPlaying() { return callback != nullptr; }
int getCurrentBufferSizeSamples() { return getBufferSizeSamples (0); }
double getCurrentSampleRate() { return getSampleRate (0); }
int getCurrentBitDepth() { return 32; }
String getLastError() { return lastError; }
BigInteger getActiveOutputChannels() const { return activeOutputChannels; }
BigInteger getActiveInputChannels() const { return activeInputChannels; }
int getOutputLatencyInSamples()
{
int latency = 0;
for (int i = 0; i < outputPorts.size(); i++)
latency = jmax (latency, (int) juce::jack_port_get_total_latency (client, (jack_port_t*) outputPorts [i]));
return latency;
}
int getInputLatencyInSamples()
{
int latency = 0;
for (int i = 0; i < inputPorts.size(); i++)
latency = jmax (latency, (int) juce::jack_port_get_total_latency (client, (jack_port_t*) inputPorts [i]));
return latency;
}
String inputId, outputId;
private:
void process (const int numSamples)
{
int numActiveInChans = 0, numActiveOutChans = 0;
for (int i = 0; i < totalNumberOfInputChannels; ++i)
{
if (activeInputChannels[i])
if (jack_default_audio_sample_t* in
= (jack_default_audio_sample_t*) juce::jack_port_get_buffer ((jack_port_t*) inputPorts.getUnchecked(i), numSamples))
inChans [numActiveInChans++] = (float*) in;
}
for (int i = 0; i < totalNumberOfOutputChannels; ++i)
{
if (activeOutputChannels[i])
if (jack_default_audio_sample_t* out
= (jack_default_audio_sample_t*) juce::jack_port_get_buffer ((jack_port_t*) outputPorts.getUnchecked(i), numSamples))
outChans [numActiveOutChans++] = (float*) out;
}
const ScopedLock sl (callbackLock);
if (callback != nullptr)
{
if ((numActiveInChans + numActiveOutChans) > 0)
callback->audioDeviceIOCallback (const_cast <const float**> (inChans.getData()), numActiveInChans,
outChans, numActiveOutChans, numSamples);
}
else
{
for (int i = 0; i < numActiveOutChans; ++i)
zeromem (outChans[i], sizeof (float) * numSamples);
}
}
static int processCallback (jack_nframes_t nframes, void* callbackArgument)
{
if (callbackArgument != nullptr)
((JackAudioIODevice*) callbackArgument)->process (nframes);
return 0;
}
void updateActivePorts()
{
BigInteger newOutputChannels, newInputChannels;
for (int i = 0; i < outputPorts.size(); ++i)
if (juce::jack_port_connected ((jack_port_t*) outputPorts.getUnchecked(i)))
newOutputChannels.setBit (i);
for (int i = 0; i < inputPorts.size(); ++i)
if (juce::jack_port_connected ((jack_port_t*) inputPorts.getUnchecked(i)))
newInputChannels.setBit (i);
if (newOutputChannels != activeOutputChannels
|| newInputChannels != activeInputChannels)
{
AudioIODeviceCallback* const oldCallback = callback;
stop();
activeOutputChannels = newOutputChannels;
activeInputChannels = newInputChannels;
if (oldCallback != nullptr)
start (oldCallback);
sendDeviceChangedCallback();
}
}
static void portConnectCallback (jack_port_id_t, jack_port_id_t, int, void* arg)
{
if (JackAudioIODevice* device = static_cast <JackAudioIODevice*> (arg))
device->updateActivePorts();
}
static void threadInitCallback (void* /* callbackArgument */)
{
jack_Log ("JackAudioIODevice::initialise");
}
static void shutdownCallback (void* callbackArgument)
{
jack_Log ("JackAudioIODevice::shutdown");
if (JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument)
{
device->client = nullptr;
device->close();
}
}
static void errorCallback (const char* msg)
{
jack_Log ("JackAudioIODevice::errorCallback " + String (msg));
}
static void sendDeviceChangedCallback();
bool isOpen_;
jack_client_t* client;
String lastError;
AudioIODeviceCallback* callback;
CriticalSection callbackLock;
HeapBlock <float*> inChans, outChans;
int totalNumberOfInputChannels;
int totalNumberOfOutputChannels;
Array<void*> inputPorts, outputPorts;
BigInteger activeInputChannels, activeOutputChannels;
};
//==============================================================================
class JackAudioIODeviceType : public AudioIODeviceType
{
public:
JackAudioIODeviceType()
: AudioIODeviceType ("JACK"),
hasScanned (false)
{
activeDeviceTypes.add (this);
}
~JackAudioIODeviceType()
{
activeDeviceTypes.removeFirstMatchingValue (this);
}
void scanForDevices()
{
hasScanned = true;
inputNames.clear();
inputIds.clear();
outputNames.clear();
outputIds.clear();
if (juce_libjackHandle == nullptr)
{
juce_libjackHandle = dlopen ("libjack.so", RTLD_LAZY);
if (juce_libjackHandle == nullptr)
return;
}
jack_status_t status;
// open a dummy client
if (jack_client_t* const client = juce::jack_client_open ("JuceJackDummy", JackNoStartServer, &status))
{
// scan for output devices
if (const char** const ports = getJackPorts (client, false))
{
for (int j = 0; ports[j] != nullptr; ++j)
{
String clientName (ports[j]);
clientName = clientName.upToFirstOccurrenceOf (":", false, false);
if (clientName != (JUCE_JACK_CLIENT_NAME) && ! inputNames.contains (clientName))
{
inputNames.add (clientName);
inputIds.add (ports [j]);
}
}
free (ports);
}
// scan for input devices
if (const char** const ports = getJackPorts (client, true))
{
for (int j = 0; ports[j] != nullptr; ++j)
{
String clientName (ports[j]);
clientName = clientName.upToFirstOccurrenceOf (":", false, false);
if (clientName != (JUCE_JACK_CLIENT_NAME) && ! outputNames.contains (clientName))
{
outputNames.add (clientName);
outputIds.add (ports [j]);
}
}
free (ports);
}
juce::jack_client_close (client);
}
else
{
dumpJackErrorMessage (status);
}
}
StringArray getDeviceNames (bool wantInputNames) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return wantInputNames ? inputNames : outputNames;
}
int getDefaultDeviceIndex (bool /* forInput */) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return 0;
}
bool hasSeparateInputsAndOutputs() const { return true; }
int getIndexOfDevice (AudioIODevice* device, bool asInput) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
if (JackAudioIODevice* d = dynamic_cast <JackAudioIODevice*> (device))
return asInput ? inputIds.indexOf (d->inputId)
: outputIds.indexOf (d->outputId);
return -1;
}
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
jassert (hasScanned); // need to call scanForDevices() before doing this
const int inputIndex = inputNames.indexOf (inputDeviceName);
const int outputIndex = outputNames.indexOf (outputDeviceName);
if (inputIndex >= 0 || outputIndex >= 0)
return new JackAudioIODevice (outputIndex >= 0 ? outputDeviceName
: inputDeviceName,
inputIds [inputIndex],
outputIds [outputIndex]);
return nullptr;
}
void portConnectionChange() { callDeviceChangeListeners(); }
private:
StringArray inputNames, outputNames, inputIds, outputIds;
bool hasScanned;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JackAudioIODeviceType)
};
void JackAudioIODevice::sendDeviceChangedCallback()
{
for (int i = activeDeviceTypes.size(); --i >= 0;)
if (JackAudioIODeviceType* d = activeDeviceTypes[i])
d->portConnectionChange();
}
//==============================================================================
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_JACK()
{
return new JackAudioIODeviceType();
}

+ 476
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_Midi.cpp View File

@@ -0,0 +1,476 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#if JUCE_ALSA
// You can define these strings in your app if you want to override the default names:
#ifndef JUCE_ALSA_MIDI_INPUT_NAME
#define JUCE_ALSA_MIDI_INPUT_NAME "Juce Midi Input"
#endif
#ifndef JUCE_ALSA_MIDI_OUTPUT_NAME
#define JUCE_ALSA_MIDI_OUTPUT_NAME "Juce Midi Output"
#endif
#ifndef JUCE_ALSA_MIDI_INPUT_PORT_NAME
#define JUCE_ALSA_MIDI_INPUT_PORT_NAME "Juce Midi In Port"
#endif
#ifndef JUCE_ALSA_MIDI_OUTPUT_PORT_NAME
#define JUCE_ALSA_MIDI_OUTPUT_PORT_NAME "Juce Midi Out Port"
#endif
//==============================================================================
namespace
{
snd_seq_t* iterateMidiClient (snd_seq_t* seqHandle,
snd_seq_client_info_t* clientInfo,
const bool forInput,
StringArray& deviceNamesFound,
const int deviceIndexToOpen)
{
snd_seq_t* returnedHandle = nullptr;
snd_seq_port_info_t* portInfo;
if (snd_seq_port_info_malloc (&portInfo) == 0)
{
int numPorts = snd_seq_client_info_get_num_ports (clientInfo);
const int client = snd_seq_client_info_get_client (clientInfo);
snd_seq_port_info_set_client (portInfo, client);
snd_seq_port_info_set_port (portInfo, -1);
while (--numPorts >= 0)
{
if (snd_seq_query_next_port (seqHandle, portInfo) == 0
&& (snd_seq_port_info_get_capability (portInfo)
& (forInput ? SND_SEQ_PORT_CAP_READ
: SND_SEQ_PORT_CAP_WRITE)) != 0)
{
deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo));
if (deviceNamesFound.size() == deviceIndexToOpen + 1)
{
const int sourcePort = snd_seq_port_info_get_port (portInfo);
const int sourceClient = snd_seq_client_info_get_client (clientInfo);
if (sourcePort != -1)
{
if (forInput)
{
snd_seq_set_client_name (seqHandle, JUCE_ALSA_MIDI_INPUT_NAME);
const int portId = snd_seq_create_simple_port (seqHandle, JUCE_ALSA_MIDI_INPUT_PORT_NAME,
SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_MIDI_GENERIC);
snd_seq_connect_from (seqHandle, portId, sourceClient, sourcePort);
}
else
{
snd_seq_set_client_name (seqHandle, JUCE_ALSA_MIDI_OUTPUT_NAME);
const int portId = snd_seq_create_simple_port (seqHandle, JUCE_ALSA_MIDI_OUTPUT_PORT_NAME,
SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ,
SND_SEQ_PORT_TYPE_MIDI_GENERIC);
snd_seq_connect_to (seqHandle, portId, sourceClient, sourcePort);
}
returnedHandle = seqHandle;
}
}
}
}
snd_seq_port_info_free (portInfo);
}
return returnedHandle;
}
snd_seq_t* iterateMidiDevices (const bool forInput,
StringArray& deviceNamesFound,
const int deviceIndexToOpen)
{
snd_seq_t* returnedHandle = nullptr;
snd_seq_t* seqHandle = nullptr;
if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
: SND_SEQ_OPEN_OUTPUT, 0) == 0)
{
snd_seq_system_info_t* systemInfo = nullptr;
snd_seq_client_info_t* clientInfo = nullptr;
if (snd_seq_system_info_malloc (&systemInfo) == 0)
{
if (snd_seq_system_info (seqHandle, systemInfo) == 0
&& snd_seq_client_info_malloc (&clientInfo) == 0)
{
int numClients = snd_seq_system_info_get_cur_clients (systemInfo);
while (--numClients >= 0 && returnedHandle == 0)
if (snd_seq_query_next_client (seqHandle, clientInfo) == 0)
returnedHandle = iterateMidiClient (seqHandle, clientInfo,
forInput, deviceNamesFound,
deviceIndexToOpen);
snd_seq_client_info_free (clientInfo);
}
snd_seq_system_info_free (systemInfo);
}
if (returnedHandle == 0)
snd_seq_close (seqHandle);
}
deviceNamesFound.appendNumbersToDuplicates (true, true);
return returnedHandle;
}
snd_seq_t* createMidiDevice (const bool forInput, const String& deviceNameToOpen)
{
snd_seq_t* seqHandle = nullptr;
if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
: SND_SEQ_OPEN_OUTPUT, 0) == 0)
{
snd_seq_set_client_name (seqHandle,
(deviceNameToOpen + (forInput ? " Input" : " Output")).toUTF8());
const int portId
= snd_seq_create_simple_port (seqHandle,
forInput ? "in"
: "out",
forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)
: (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ),
forInput ? SND_SEQ_PORT_TYPE_APPLICATION
: SND_SEQ_PORT_TYPE_MIDI_GENERIC);
if (portId < 0)
{
snd_seq_close (seqHandle);
seqHandle = nullptr;
}
}
return seqHandle;
}
}
//==============================================================================
class MidiOutputDevice
{
public:
MidiOutputDevice (MidiOutput* const midiOutput_,
snd_seq_t* const seqHandle_)
:
midiOutput (midiOutput_),
seqHandle (seqHandle_),
maxEventSize (16 * 1024)
{
jassert (seqHandle != 0 && midiOutput != 0);
snd_midi_event_new (maxEventSize, &midiParser);
}
~MidiOutputDevice()
{
snd_midi_event_free (midiParser);
snd_seq_close (seqHandle);
}
void sendMessageNow (const MidiMessage& message)
{
if (message.getRawDataSize() > maxEventSize)
{
maxEventSize = message.getRawDataSize();
snd_midi_event_free (midiParser);
snd_midi_event_new (maxEventSize, &midiParser);
}
snd_seq_event_t event;
snd_seq_ev_clear (&event);
long numBytes = (long) message.getRawDataSize();
const uint8* data = message.getRawData();
while (numBytes > 0)
{
const long numSent = snd_midi_event_encode (midiParser, data, numBytes, &event);
if (numSent <= 0)
break;
numBytes -= numSent;
data += numSent;
snd_seq_ev_set_source (&event, 0);
snd_seq_ev_set_subs (&event);
snd_seq_ev_set_direct (&event);
snd_seq_event_output (seqHandle, &event);
}
snd_seq_drain_output (seqHandle);
snd_midi_event_reset_encode (midiParser);
}
private:
MidiOutput* const midiOutput;
snd_seq_t* const seqHandle;
snd_midi_event_t* midiParser;
int maxEventSize;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiOutputDevice)
};
StringArray MidiOutput::getDevices()
{
StringArray devices;
iterateMidiDevices (false, devices, -1);
return devices;
}
int MidiOutput::getDefaultDeviceIndex()
{
return 0;
}
MidiOutput* MidiOutput::openDevice (int deviceIndex)
{
MidiOutput* newDevice = nullptr;
StringArray devices;
snd_seq_t* const handle = iterateMidiDevices (false, devices, deviceIndex);
if (handle != 0)
{
newDevice = new MidiOutput();
newDevice->internal = new MidiOutputDevice (newDevice, handle);
}
return newDevice;
}
MidiOutput* MidiOutput::createNewDevice (const String& deviceName)
{
MidiOutput* newDevice = nullptr;
snd_seq_t* const handle = createMidiDevice (false, deviceName);
if (handle != 0)
{
newDevice = new MidiOutput();
newDevice->internal = new MidiOutputDevice (newDevice, handle);
}
return newDevice;
}
MidiOutput::~MidiOutput()
{
delete static_cast <MidiOutputDevice*> (internal);
}
void MidiOutput::sendMessageNow (const MidiMessage& message)
{
static_cast <MidiOutputDevice*> (internal)->sendMessageNow (message);
}
//==============================================================================
class MidiInputThread : public Thread
{
public:
MidiInputThread (MidiInput* const midiInput_,
snd_seq_t* const seqHandle_,
MidiInputCallback* const callback_)
: Thread ("Juce MIDI Input"),
midiInput (midiInput_),
seqHandle (seqHandle_),
callback (callback_)
{
jassert (seqHandle != 0 && callback != 0 && midiInput != 0);
}
~MidiInputThread()
{
snd_seq_close (seqHandle);
}
void run()
{
const int maxEventSize = 16 * 1024;
snd_midi_event_t* midiParser;
if (snd_midi_event_new (maxEventSize, &midiParser) >= 0)
{
HeapBlock <uint8> buffer (maxEventSize);
const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN);
struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd));
snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN);
while (! threadShouldExit())
{
if (poll (pfd, numPfds, 500) > 0)
{
snd_seq_event_t* inputEvent = nullptr;
snd_seq_nonblock (seqHandle, 1);
do
{
if (snd_seq_event_input (seqHandle, &inputEvent) >= 0)
{
// xxx what about SYSEXes that are too big for the buffer?
const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent);
snd_midi_event_reset_decode (midiParser);
if (numBytes > 0)
{
const MidiMessage message ((const uint8*) buffer,
numBytes,
Time::getMillisecondCounter() * 0.001);
callback->handleIncomingMidiMessage (midiInput, message);
}
snd_seq_free_event (inputEvent);
}
}
while (snd_seq_event_input_pending (seqHandle, 0) > 0);
snd_seq_free_event (inputEvent);
}
}
snd_midi_event_free (midiParser);
}
};
private:
MidiInput* const midiInput;
snd_seq_t* const seqHandle;
MidiInputCallback* const callback;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiInputThread)
};
//==============================================================================
MidiInput::MidiInput (const String& name_)
: name (name_),
internal (0)
{
}
MidiInput::~MidiInput()
{
stop();
delete static_cast <MidiInputThread*> (internal);
}
void MidiInput::start()
{
static_cast <MidiInputThread*> (internal)->startThread();
}
void MidiInput::stop()
{
static_cast <MidiInputThread*> (internal)->stopThread (3000);
}
int MidiInput::getDefaultDeviceIndex()
{
return 0;
}
StringArray MidiInput::getDevices()
{
StringArray devices;
iterateMidiDevices (true, devices, -1);
return devices;
}
MidiInput* MidiInput::openDevice (int deviceIndex, MidiInputCallback* callback)
{
MidiInput* newDevice = nullptr;
StringArray devices;
snd_seq_t* const handle = iterateMidiDevices (true, devices, deviceIndex);
if (handle != 0)
{
newDevice = new MidiInput (devices [deviceIndex]);
newDevice->internal = new MidiInputThread (newDevice, handle, callback);
}
return newDevice;
}
MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback)
{
MidiInput* newDevice = nullptr;
snd_seq_t* const handle = createMidiDevice (true, deviceName);
if (handle != 0)
{
newDevice = new MidiInput (deviceName);
newDevice->internal = new MidiInputThread (newDevice, handle, callback);
}
return newDevice;
}
//==============================================================================
#else
// (These are just stub functions if ALSA is unavailable...)
StringArray MidiOutput::getDevices() { return StringArray(); }
int MidiOutput::getDefaultDeviceIndex() { return 0; }
MidiOutput* MidiOutput::openDevice (int) { return nullptr; }
MidiOutput* MidiOutput::createNewDevice (const String&) { return nullptr; }
MidiOutput::~MidiOutput() {}
void MidiOutput::sendMessageNow (const MidiMessage&) {}
MidiInput::MidiInput (const String& name_) : name (name_), internal (0) {}
MidiInput::~MidiInput() {}
void MidiInput::start() {}
void MidiInput::stop() {}
int MidiInput::getDefaultDeviceIndex() { return 0; }
StringArray MidiInput::getDevices() { return StringArray(); }
MidiInput* MidiInput::openDevice (int, MidiInputCallback*) { return nullptr; }
MidiInput* MidiInput::createNewDevice (const String&, MidiInputCallback*) { return nullptr; }
#endif

+ 492
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDBurner.mm View File

@@ -0,0 +1,492 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
const int kilobytesPerSecond1x = 176;
struct AudioTrackProducerClass : public ObjCClass <NSObject>
{
AudioTrackProducerClass() : ObjCClass <NSObject> ("JUCEAudioTrackProducer_")
{
addIvar<AudioSourceHolder*> ("source");
addMethod (@selector (initWithAudioSourceHolder:), initWithAudioSourceHolder, "@@:^v");
addMethod (@selector (cleanupTrackAfterBurn:), cleanupTrackAfterBurn, "v@:@");
addMethod (@selector (cleanupTrackAfterVerification:), cleanupTrackAfterVerification, "c@:@");
addMethod (@selector (estimateLengthOfTrack:), estimateLengthOfTrack, "Q@:@");
addMethod (@selector (prepareTrack:forBurn:toMedia:), prepareTrack, "c@:@@@");
addMethod (@selector (prepareTrackForVerification:), prepareTrackForVerification, "c@:@");
addMethod (@selector (produceDataForTrack:intoBuffer:length:atAddress:blockSize:ioFlags:),
produceDataForTrack, "I@:@^cIQI^I");
addMethod (@selector (producePreGapForTrack:intoBuffer:length:atAddress:blockSize:ioFlags:),
produceDataForTrack, "I@:@^cIQI^I");
addMethod (@selector (verifyDataForTrack:intoBuffer:length:atAddress:blockSize:ioFlags:),
produceDataForTrack, "I@:@^cIQI^I");
registerClass();
}
struct AudioSourceHolder
{
AudioSourceHolder (AudioSource* source_, int numFrames)
: source (source_), readPosition (0), lengthInFrames (numFrames)
{
}
~AudioSourceHolder()
{
if (source != nullptr)
source->releaseResources();
}
ScopedPointer<AudioSource> source;
int readPosition, lengthInFrames;
};
private:
static id initWithAudioSourceHolder (id self, SEL, AudioSourceHolder* source)
{
self = sendSuperclassMessage (self, @selector (init));
object_setInstanceVariable (self, "source", source);
return self;
}
static AudioSourceHolder* getSource (id self)
{
return getIvar<AudioSourceHolder*> (self, "source");
}
static void dealloc (id self, SEL)
{
delete getSource (self);
sendSuperclassMessage (self, @selector (dealloc));
}
static void cleanupTrackAfterBurn (id self, SEL, DRTrack*) {}
static BOOL cleanupTrackAfterVerification (id self, SEL, DRTrack*) { return true; }
static uint64_t estimateLengthOfTrack (id self, SEL, DRTrack*)
{
return getSource (self)->lengthInFrames;
}
static BOOL prepareTrack (id self, SEL, DRTrack*, DRBurn*, NSDictionary*)
{
if (AudioSourceHolder* const source = getSource (self))
{
source->source->prepareToPlay (44100 / 75, 44100);
source->readPosition = 0;
}
return true;
}
static BOOL prepareTrackForVerification (id self, SEL, DRTrack*)
{
if (AudioSourceHolder* const source = getSource (self))
source->source->prepareToPlay (44100 / 75, 44100);
return true;
}
static uint32_t produceDataForTrack (id self, SEL, DRTrack*, char* buffer,
uint32_t bufferLength, uint64_t /*address*/,
uint32_t /*blockSize*/, uint32_t* /*flags*/)
{
if (AudioSourceHolder* const source = getSource (self))
{
const int numSamples = jmin ((int) bufferLength / 4,
(source->lengthInFrames * (44100 / 75)) - source->readPosition);
if (numSamples > 0)
{
AudioSampleBuffer tempBuffer (2, numSamples);
AudioSourceChannelInfo info (tempBuffer);
source->source->getNextAudioBlock (info);
typedef AudioData::Pointer <AudioData::Int16,
AudioData::LittleEndian,
AudioData::Interleaved,
AudioData::NonConst> CDSampleFormat;
typedef AudioData::Pointer <AudioData::Float32,
AudioData::NativeEndian,
AudioData::NonInterleaved,
AudioData::Const> SourceSampleFormat;
CDSampleFormat left (buffer, 2);
left.convertSamples (SourceSampleFormat (tempBuffer.getSampleData (0)), numSamples);
CDSampleFormat right (buffer + 2, 2);
right.convertSamples (SourceSampleFormat (tempBuffer.getSampleData (1)), numSamples);
source->readPosition += numSamples;
}
return numSamples * 4;
}
return 0;
}
static uint32_t producePreGapForTrack (id self, SEL, DRTrack*, char* buffer,
uint32_t bufferLength, uint64_t /*address*/,
uint32_t /*blockSize*/, uint32_t* /*flags*/)
{
zeromem (buffer, bufferLength);
return bufferLength;
}
static BOOL verifyDataForTrack (id self, SEL, DRTrack*, const char*,
uint32_t /*bufferLength*/, uint64_t /*address*/,
uint32_t /*blockSize*/, uint32_t* /*flags*/)
{
return true;
}
};
struct OpenDiskDevice
{
OpenDiskDevice (DRDevice* device_)
: device (device_),
tracks ([[NSMutableArray alloc] init]),
underrunProtection (true)
{
}
~OpenDiskDevice()
{
[tracks release];
}
void addSourceTrack (AudioSource* source, int numSamples)
{
if (source != nullptr)
{
const int numFrames = (numSamples + 587) / 588;
static AudioTrackProducerClass cls;
NSObject* producer = [cls.createInstance() performSelector: @selector (initWithAudioSourceHolder:)
withObject: (id) new AudioTrackProducerClass::AudioSourceHolder (source, numFrames)];
DRTrack* track = [[DRTrack alloc] initWithProducer: producer];
{
NSMutableDictionary* p = [[track properties] mutableCopy];
[p setObject: [DRMSF msfWithFrames: numFrames] forKey: DRTrackLengthKey];
[p setObject: [NSNumber numberWithUnsignedShort: 2352] forKey: DRBlockSizeKey];
[p setObject: [NSNumber numberWithInt: 0] forKey: DRDataFormKey];
[p setObject: [NSNumber numberWithInt: 0] forKey: DRBlockTypeKey];
[p setObject: [NSNumber numberWithInt: 0] forKey: DRTrackModeKey];
[p setObject: [NSNumber numberWithInt: 0] forKey: DRSessionFormatKey];
[track setProperties: p];
[p release];
}
[tracks addObject: track];
[track release];
[producer release];
}
}
String burn (AudioCDBurner::BurnProgressListener* listener,
bool shouldEject, bool peformFakeBurnForTesting, int burnSpeed)
{
DRBurn* burn = [DRBurn burnForDevice: device];
if (! [device acquireExclusiveAccess])
return "Couldn't open or write to the CD device";
[device acquireMediaReservation];
NSMutableDictionary* d = [[burn properties] mutableCopy];
[d autorelease];
[d setObject: [NSNumber numberWithBool: peformFakeBurnForTesting] forKey: DRBurnTestingKey];
[d setObject: [NSNumber numberWithBool: false] forKey: DRBurnVerifyDiscKey];
[d setObject: (shouldEject ? DRBurnCompletionActionEject : DRBurnCompletionActionMount) forKey: DRBurnCompletionActionKey];
if (burnSpeed > 0)
[d setObject: [NSNumber numberWithFloat: burnSpeed * kilobytesPerSecond1x] forKey: DRBurnRequestedSpeedKey];
if (! underrunProtection)
[d setObject: [NSNumber numberWithBool: false] forKey: DRBurnUnderrunProtectionKey];
[burn setProperties: d];
[burn writeLayout: tracks];
for (;;)
{
Thread::sleep (300);
float progress = [[[burn status] objectForKey: DRStatusPercentCompleteKey] floatValue];
if (listener != nullptr && listener->audioCDBurnProgress (progress))
{
[burn abort];
return "User cancelled the write operation";
}
if ([[[burn status] objectForKey: DRStatusStateKey] isEqualTo: DRStatusStateFailed])
return "Write operation failed";
if ([[[burn status] objectForKey: DRStatusStateKey] isEqualTo: DRStatusStateDone])
break;
NSString* err = (NSString*) [[[burn status] objectForKey: DRErrorStatusKey]
objectForKey: DRErrorStatusErrorStringKey];
if ([err length] > 0)
return CharPointer_UTF8 ([err UTF8String]);
}
[device releaseMediaReservation];
[device releaseExclusiveAccess];
return String::empty;
}
DRDevice* device;
NSMutableArray* tracks;
bool underrunProtection;
};
//==============================================================================
class AudioCDBurner::Pimpl : public Timer
{
public:
Pimpl (AudioCDBurner& owner_, const int deviceIndex)
: device (0), owner (owner_)
{
DRDevice* dev = [[DRDevice devices] objectAtIndex: deviceIndex];
if (dev != nil)
{
device = new OpenDiskDevice (dev);
lastState = getDiskState();
startTimer (1000);
}
}
~Pimpl()
{
stopTimer();
}
void timerCallback()
{
const DiskState state = getDiskState();
if (state != lastState)
{
lastState = state;
owner.sendChangeMessage();
}
}
DiskState getDiskState() const
{
if ([device->device isValid])
{
NSDictionary* status = [device->device status];
NSString* state = [status objectForKey: DRDeviceMediaStateKey];
if ([state isEqualTo: DRDeviceMediaStateNone])
{
if ([[status objectForKey: DRDeviceIsTrayOpenKey] boolValue])
return trayOpen;
return noDisc;
}
if ([state isEqualTo: DRDeviceMediaStateMediaPresent])
{
if ([[[status objectForKey: DRDeviceMediaInfoKey] objectForKey: DRDeviceMediaBlocksFreeKey] intValue] > 0)
return writableDiskPresent;
else
return readOnlyDiskPresent;
}
}
return unknown;
}
bool openTray() { return [device->device isValid] && [device->device ejectMedia]; }
Array<int> getAvailableWriteSpeeds() const
{
Array<int> results;
if ([device->device isValid])
{
NSArray* speeds = [[[device->device status] objectForKey: DRDeviceMediaInfoKey] objectForKey: DRDeviceBurnSpeedsKey];
for (unsigned int i = 0; i < [speeds count]; ++i)
{
const int kbPerSec = [[speeds objectAtIndex: i] intValue];
results.add (kbPerSec / kilobytesPerSecond1x);
}
}
return results;
}
bool setBufferUnderrunProtection (const bool shouldBeEnabled)
{
if ([device->device isValid])
{
device->underrunProtection = shouldBeEnabled;
return shouldBeEnabled && [[[device->device status] objectForKey: DRDeviceCanUnderrunProtectCDKey] boolValue];
}
return false;
}
int getNumAvailableAudioBlocks() const
{
return [[[[device->device status] objectForKey: DRDeviceMediaInfoKey]
objectForKey: DRDeviceMediaBlocksFreeKey] intValue];
}
ScopedPointer<OpenDiskDevice> device;
private:
DiskState lastState;
AudioCDBurner& owner;
};
//==============================================================================
AudioCDBurner::AudioCDBurner (const int deviceIndex)
{
pimpl = new Pimpl (*this, deviceIndex);
}
AudioCDBurner::~AudioCDBurner()
{
}
AudioCDBurner* AudioCDBurner::openDevice (const int deviceIndex)
{
ScopedPointer <AudioCDBurner> b (new AudioCDBurner (deviceIndex));
if (b->pimpl->device == nil)
b = 0;
return b.release();
}
namespace
{
NSArray* findDiskBurnerDevices()
{
NSMutableArray* results = [NSMutableArray array];
NSArray* devs = [DRDevice devices];
for (int i = 0; i < [devs count]; ++i)
{
NSDictionary* dic = [[devs objectAtIndex: i] info];
NSString* name = [dic valueForKey: DRDeviceProductNameKey];
if (name != nil)
[results addObject: name];
}
return results;
}
}
StringArray AudioCDBurner::findAvailableDevices()
{
NSArray* names = findDiskBurnerDevices();
StringArray s;
for (unsigned int i = 0; i < [names count]; ++i)
s.add (CharPointer_UTF8 ([[names objectAtIndex: i] UTF8String]));
return s;
}
AudioCDBurner::DiskState AudioCDBurner::getDiskState() const
{
return pimpl->getDiskState();
}
bool AudioCDBurner::isDiskPresent() const
{
return getDiskState() == writableDiskPresent;
}
bool AudioCDBurner::openTray()
{
return pimpl->openTray();
}
AudioCDBurner::DiskState AudioCDBurner::waitUntilStateChange (int timeOutMilliseconds)
{
const int64 timeout = Time::currentTimeMillis() + timeOutMilliseconds;
DiskState oldState = getDiskState();
DiskState newState = oldState;
while (newState == oldState && Time::currentTimeMillis() < timeout)
{
newState = getDiskState();
Thread::sleep (100);
}
return newState;
}
Array<int> AudioCDBurner::getAvailableWriteSpeeds() const
{
return pimpl->getAvailableWriteSpeeds();
}
bool AudioCDBurner::setBufferUnderrunProtection (const bool shouldBeEnabled)
{
return pimpl->setBufferUnderrunProtection (shouldBeEnabled);
}
int AudioCDBurner::getNumAvailableAudioBlocks() const
{
return pimpl->getNumAvailableAudioBlocks();
}
bool AudioCDBurner::addAudioTrack (AudioSource* source, int numSamps)
{
if ([pimpl->device->device isValid])
{
pimpl->device->addSourceTrack (source, numSamps);
return true;
}
return false;
}
String AudioCDBurner::burn (AudioCDBurner::BurnProgressListener* listener,
bool ejectDiscAfterwards,
bool performFakeBurnForTesting,
int writeSpeed)
{
if ([pimpl->device->device isValid])
return pimpl->device->burn (listener, ejectDiscAfterwards, performFakeBurnForTesting, writeSpeed);
return "Couldn't open or write to the CD device";
}

+ 260
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm View File

@@ -0,0 +1,260 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
namespace CDReaderHelpers
{
inline const XmlElement* getElementForKey (const XmlElement& xml, const String& key)
{
forEachXmlChildElementWithTagName (xml, child, "key")
if (child->getAllSubText().trim() == key)
return child->getNextElement();
return nullptr;
}
static int getIntValueForKey (const XmlElement& xml, const String& key, int defaultValue = -1)
{
const XmlElement* const block = getElementForKey (xml, key);
return block != nullptr ? block->getAllSubText().trim().getIntValue() : defaultValue;
}
// Get the track offsets for a CD given an XmlElement representing its TOC.Plist.
// Returns NULL on success, otherwise a const char* representing an error.
static const char* getTrackOffsets (XmlDocument& xmlDocument, Array<int>& offsets)
{
const ScopedPointer<XmlElement> xml (xmlDocument.getDocumentElement());
if (xml == nullptr)
return "Couldn't parse XML in file";
const XmlElement* const dict = xml->getChildByName ("dict");
if (dict == nullptr)
return "Couldn't get top level dictionary";
const XmlElement* const sessions = getElementForKey (*dict, "Sessions");
if (sessions == nullptr)
return "Couldn't find sessions key";
const XmlElement* const session = sessions->getFirstChildElement();
if (session == nullptr)
return "Couldn't find first session";
const int leadOut = getIntValueForKey (*session, "Leadout Block");
if (leadOut < 0)
return "Couldn't find Leadout Block";
const XmlElement* const trackArray = getElementForKey (*session, "Track Array");
if (trackArray == nullptr)
return "Couldn't find Track Array";
forEachXmlChildElement (*trackArray, track)
{
const int trackValue = getIntValueForKey (*track, "Start Block");
if (trackValue < 0)
return "Couldn't find Start Block in the track";
offsets.add (trackValue * AudioCDReader::samplesPerFrame - 88200);
}
offsets.add (leadOut * AudioCDReader::samplesPerFrame - 88200);
return nullptr;
}
static void findDevices (Array<File>& cds)
{
File volumes ("/Volumes");
volumes.findChildFiles (cds, File::findDirectories, false);
for (int i = cds.size(); --i >= 0;)
if (! cds.getReference(i).getChildFile (".TOC.plist").exists())
cds.remove (i);
}
struct TrackSorter
{
static int getCDTrackNumber (const File& file)
{
return file.getFileName().initialSectionContainingOnly ("0123456789").getIntValue();
}
static int compareElements (const File& first, const File& second)
{
const int firstTrack = getCDTrackNumber (first);
const int secondTrack = getCDTrackNumber (second);
jassert (firstTrack > 0 && secondTrack > 0);
return firstTrack - secondTrack;
}
};
}
//==============================================================================
StringArray AudioCDReader::getAvailableCDNames()
{
Array<File> cds;
CDReaderHelpers::findDevices (cds);
StringArray names;
for (int i = 0; i < cds.size(); ++i)
names.add (cds.getReference(i).getFileName());
return names;
}
AudioCDReader* AudioCDReader::createReaderForCD (const int index)
{
Array<File> cds;
CDReaderHelpers::findDevices (cds);
if (cds[index].exists())
return new AudioCDReader (cds[index]);
return nullptr;
}
AudioCDReader::AudioCDReader (const File& volume)
: AudioFormatReader (0, "CD Audio"),
volumeDir (volume),
currentReaderTrack (-1),
reader (0)
{
sampleRate = 44100.0;
bitsPerSample = 16;
numChannels = 2;
usesFloatingPointData = false;
refreshTrackLengths();
}
AudioCDReader::~AudioCDReader()
{
}
void AudioCDReader::refreshTrackLengths()
{
tracks.clear();
trackStartSamples.clear();
lengthInSamples = 0;
volumeDir.findChildFiles (tracks, File::findFiles | File::ignoreHiddenFiles, false, "*.aiff");
CDReaderHelpers::TrackSorter sorter;
tracks.sort (sorter);
const File toc (volumeDir.getChildFile (".TOC.plist"));
if (toc.exists())
{
XmlDocument doc (toc);
const char* error = CDReaderHelpers::getTrackOffsets (doc, trackStartSamples);
(void) error; // could be logged..
lengthInSamples = trackStartSamples.getLast() - trackStartSamples.getFirst();
}
}
bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
int64 startSampleInFile, int numSamples)
{
while (numSamples > 0)
{
int track = -1;
for (int i = 0; i < trackStartSamples.size() - 1; ++i)
{
if (startSampleInFile < trackStartSamples.getUnchecked (i + 1))
{
track = i;
break;
}
}
if (track < 0)
return false;
if (track != currentReaderTrack)
{
reader = nullptr;
if (FileInputStream* const in = tracks [track].createInputStream())
{
BufferedInputStream* const bin = new BufferedInputStream (in, 65536, true);
AiffAudioFormat format;
reader = format.createReaderFor (bin, true);
if (reader == nullptr)
currentReaderTrack = -1;
else
currentReaderTrack = track;
}
}
if (reader == nullptr)
return false;
const int startPos = (int) (startSampleInFile - trackStartSamples.getUnchecked (track));
const int numAvailable = (int) jmin ((int64) numSamples, reader->lengthInSamples - startPos);
reader->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, startPos, numAvailable);
numSamples -= numAvailable;
startSampleInFile += numAvailable;
}
return true;
}
bool AudioCDReader::isCDStillPresent() const
{
return volumeDir.exists();
}
void AudioCDReader::ejectDisk()
{
JUCE_AUTORELEASEPOOL
[[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: juceStringToNS (volumeDir.getFullPathName())];
}
bool AudioCDReader::isTrackAudio (int trackNum) const
{
return tracks [trackNum].hasFileExtension (".aiff");
}
void AudioCDReader::enableIndexScanning (bool)
{
// any way to do this on a Mac??
}
int AudioCDReader::getLastIndex() const
{
return 0;
}
Array<int> AudioCDReader::findIndexesInTrack (const int /*trackNumber*/)
{
return Array<int>();
}

+ 1269
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
File diff suppressed because it is too large
View File


+ 523
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp View File

@@ -0,0 +1,523 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
namespace CoreMidiHelpers
{
static bool logError (const OSStatus err, const int lineNum)
{
if (err == noErr)
return true;
Logger::writeToLog ("CoreMidi error: " + String (lineNum) + " - " + String::toHexString ((int) err));
jassertfalse;
return false;
}
#undef CHECK_ERROR
#define CHECK_ERROR(a) CoreMidiHelpers::logError (a, __LINE__)
//==============================================================================
static String getMidiObjectName (MIDIObjectRef entity)
{
String result;
CFStringRef str = 0;
MIDIObjectGetStringProperty (entity, kMIDIPropertyName, &str);
if (str != 0)
{
result = String::fromCFString (str);
CFRelease (str);
}
return result;
}
static String getEndpointName (MIDIEndpointRef endpoint, bool isExternal)
{
String result (getMidiObjectName (endpoint));
MIDIEntityRef entity = 0;
MIDIEndpointGetEntity (endpoint, &entity);
if (entity == 0)
return result; // probably virtual
if (result.isEmpty())
result = getMidiObjectName (entity); // endpoint name is empty - try the entity
// now consider the device's name
MIDIDeviceRef device = 0;
MIDIEntityGetDevice (entity, &device);
if (device != 0)
{
const String deviceName (getMidiObjectName (device));
if (deviceName.isNotEmpty())
{
// if an external device has only one entity, throw away
// the endpoint name and just use the device name
if (isExternal && MIDIDeviceGetNumberOfEntities (device) < 2)
{
result = deviceName;
}
else if (! result.startsWithIgnoreCase (deviceName))
{
// prepend the device name to the entity name
result = (deviceName + " " + result).trimEnd();
}
}
}
return result;
}
static String getConnectedEndpointName (MIDIEndpointRef endpoint)
{
String result;
// Does the endpoint have connections?
CFDataRef connections = 0;
int numConnections = 0;
MIDIObjectGetDataProperty (endpoint, kMIDIPropertyConnectionUniqueID, &connections);
if (connections != 0)
{
numConnections = ((int) CFDataGetLength (connections)) / (int) sizeof (MIDIUniqueID);
if (numConnections > 0)
{
const SInt32* pid = reinterpret_cast <const SInt32*> (CFDataGetBytePtr (connections));
for (int i = 0; i < numConnections; ++i, ++pid)
{
MIDIUniqueID uid = (MIDIUniqueID) ByteOrder::swapIfLittleEndian ((uint32) *pid);
MIDIObjectRef connObject;
MIDIObjectType connObjectType;
OSStatus err = MIDIObjectFindByUniqueID (uid, &connObject, &connObjectType);
if (err == noErr)
{
String s;
if (connObjectType == kMIDIObjectType_ExternalSource
|| connObjectType == kMIDIObjectType_ExternalDestination)
{
// Connected to an external device's endpoint (10.3 and later).
s = getEndpointName (static_cast <MIDIEndpointRef> (connObject), true);
}
else
{
// Connected to an external device (10.2) (or something else, catch-all)
s = getMidiObjectName (connObject);
}
if (s.isNotEmpty())
{
if (result.isNotEmpty())
result += ", ";
result += s;
}
}
}
}
CFRelease (connections);
}
if (result.isEmpty()) // Here, either the endpoint had no connections, or we failed to obtain names for them.
result = getEndpointName (endpoint, false);
return result;
}
static StringArray findDevices (const bool forInput)
{
const ItemCount num = forInput ? MIDIGetNumberOfSources()
: MIDIGetNumberOfDestinations();
StringArray s;
for (ItemCount i = 0; i < num; ++i)
{
MIDIEndpointRef dest = forInput ? MIDIGetSource (i)
: MIDIGetDestination (i);
String name;
if (dest != 0)
name = getConnectedEndpointName (dest);
if (name.isEmpty())
name = "<error>";
s.add (name);
}
return s;
}
static void globalSystemChangeCallback (const MIDINotification*, void*)
{
// TODO.. Should pass-on this notification..
}
static String getGlobalMidiClientName()
{
JUCEApplicationBase* const app = JUCEApplicationBase::getInstance();
return app != nullptr ? app->getApplicationName() : "JUCE";
}
static MIDIClientRef getGlobalMidiClient()
{
static MIDIClientRef globalMidiClient = 0;
if (globalMidiClient == 0)
{
// Since OSX 10.6, the MIDIClientCreate function will only work
// correctly when called from the message thread!
jassert (MessageManager::getInstance()->isThisTheMessageThread());
CFStringRef name = getGlobalMidiClientName().toCFString();
CHECK_ERROR (MIDIClientCreate (name, &globalSystemChangeCallback, 0, &globalMidiClient));
CFRelease (name);
}
return globalMidiClient;
}
//==============================================================================
class MidiPortAndEndpoint
{
public:
MidiPortAndEndpoint (MIDIPortRef port_, MIDIEndpointRef endPoint_)
: port (port_), endPoint (endPoint_)
{
}
~MidiPortAndEndpoint()
{
if (port != 0)
MIDIPortDispose (port);
if (port == 0 && endPoint != 0) // if port == 0, it means we created the endpoint, so it's safe to delete it
MIDIEndpointDispose (endPoint);
}
void send (const MIDIPacketList* const packets)
{
if (port != 0)
MIDISend (port, endPoint, packets);
else
MIDIReceived (endPoint, packets);
}
MIDIPortRef port;
MIDIEndpointRef endPoint;
};
//==============================================================================
class MidiPortAndCallback;
CriticalSection callbackLock;
Array<MidiPortAndCallback*> activeCallbacks;
class MidiPortAndCallback
{
public:
MidiPortAndCallback (MidiInputCallback& callback_)
: input (nullptr), active (false), callback (callback_), concatenator (2048)
{
}
~MidiPortAndCallback()
{
active = false;
{
const ScopedLock sl (callbackLock);
activeCallbacks.removeFirstMatchingValue (this);
}
if (portAndEndpoint != nullptr && portAndEndpoint->port != 0)
CHECK_ERROR (MIDIPortDisconnectSource (portAndEndpoint->port, portAndEndpoint->endPoint));
}
void handlePackets (const MIDIPacketList* const pktlist)
{
const double time = Time::getMillisecondCounterHiRes() * 0.001;
const ScopedLock sl (callbackLock);
if (activeCallbacks.contains (this) && active)
{
const MIDIPacket* packet = &pktlist->packet[0];
for (unsigned int i = 0; i < pktlist->numPackets; ++i)
{
concatenator.pushMidiData (packet->data, (int) packet->length, time,
input, callback);
packet = MIDIPacketNext (packet);
}
}
}
MidiInput* input;
ScopedPointer<MidiPortAndEndpoint> portAndEndpoint;
volatile bool active;
private:
MidiInputCallback& callback;
MidiDataConcatenator concatenator;
};
static void midiInputProc (const MIDIPacketList* pktlist, void* readProcRefCon, void* /*srcConnRefCon*/)
{
static_cast <MidiPortAndCallback*> (readProcRefCon)->handlePackets (pktlist);
}
}
//==============================================================================
StringArray MidiOutput::getDevices() { return CoreMidiHelpers::findDevices (false); }
int MidiOutput::getDefaultDeviceIndex() { return 0; }
MidiOutput* MidiOutput::openDevice (int index)
{
MidiOutput* mo = nullptr;
if (isPositiveAndBelow (index, (int) MIDIGetNumberOfDestinations()))
{
MIDIEndpointRef endPoint = MIDIGetDestination ((ItemCount) index);
CFStringRef pname;
if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname)))
{
MIDIClientRef client = CoreMidiHelpers::getGlobalMidiClient();
MIDIPortRef port;
if (client != 0 && CHECK_ERROR (MIDIOutputPortCreate (client, pname, &port)))
{
mo = new MidiOutput();
mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (port, endPoint);
}
CFRelease (pname);
}
}
return mo;
}
MidiOutput* MidiOutput::createNewDevice (const String& deviceName)
{
MidiOutput* mo = nullptr;
MIDIClientRef client = CoreMidiHelpers::getGlobalMidiClient();
MIDIEndpointRef endPoint;
CFStringRef name = deviceName.toCFString();
if (client != 0 && CHECK_ERROR (MIDISourceCreate (client, name, &endPoint)))
{
mo = new MidiOutput();
mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (0, endPoint);
}
CFRelease (name);
return mo;
}
MidiOutput::~MidiOutput()
{
delete static_cast<CoreMidiHelpers::MidiPortAndEndpoint*> (internal);
}
void MidiOutput::sendMessageNow (const MidiMessage& message)
{
#if JUCE_IOS
const MIDITimeStamp timeStamp = mach_absolute_time();
#else
const MIDITimeStamp timeStamp = AudioGetCurrentHostTime();
#endif
HeapBlock <MIDIPacketList> allocatedPackets;
MIDIPacketList stackPacket;
MIDIPacketList* packetToSend = &stackPacket;
const size_t dataSize = (size_t) message.getRawDataSize();
if (message.isSysEx())
{
const int maxPacketSize = 256;
int pos = 0, bytesLeft = (int) dataSize;
const int numPackets = (bytesLeft + maxPacketSize - 1) / maxPacketSize;
allocatedPackets.malloc ((size_t) (32 * (size_t) numPackets + dataSize), 1);
packetToSend = allocatedPackets;
packetToSend->numPackets = (UInt32) numPackets;
MIDIPacket* p = packetToSend->packet;
for (int i = 0; i < numPackets; ++i)
{
p->timeStamp = timeStamp;
p->length = (UInt16) jmin (maxPacketSize, bytesLeft);
memcpy (p->data, message.getRawData() + pos, p->length);
pos += p->length;
bytesLeft -= p->length;
p = MIDIPacketNext (p);
}
}
else if (dataSize < 65536) // max packet size
{
const size_t stackCapacity = sizeof (stackPacket.packet->data);
if (dataSize > stackCapacity)
{
allocatedPackets.malloc ((sizeof (MIDIPacketList) - stackCapacity) + dataSize, 1);
packetToSend = allocatedPackets;
}
packetToSend->numPackets = 1;
MIDIPacket& p = *(packetToSend->packet);
p.timeStamp = timeStamp;
p.length = (UInt16) dataSize;
memcpy (p.data, message.getRawData(), dataSize);
}
else
{
jassertfalse; // packet too large to send!
return;
}
static_cast<CoreMidiHelpers::MidiPortAndEndpoint*> (internal)->send (packetToSend);
}
//==============================================================================
StringArray MidiInput::getDevices() { return CoreMidiHelpers::findDevices (true); }
int MidiInput::getDefaultDeviceIndex() { return 0; }
MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback)
{
jassert (callback != 0);
using namespace CoreMidiHelpers;
MidiInput* newInput = nullptr;
if (isPositiveAndBelow (index, (int) MIDIGetNumberOfSources()))
{
MIDIEndpointRef endPoint = MIDIGetSource ((ItemCount) index);
if (endPoint != 0)
{
CFStringRef name;
if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &name)))
{
if (MIDIClientRef client = getGlobalMidiClient())
{
MIDIPortRef port;
ScopedPointer <MidiPortAndCallback> mpc (new MidiPortAndCallback (*callback));
if (CHECK_ERROR (MIDIInputPortCreate (client, name, midiInputProc, mpc, &port)))
{
if (CHECK_ERROR (MIDIPortConnectSource (port, endPoint, 0)))
{
mpc->portAndEndpoint = new MidiPortAndEndpoint (port, endPoint);
newInput = new MidiInput (getDevices() [index]);
mpc->input = newInput;
newInput->internal = mpc;
const ScopedLock sl (callbackLock);
activeCallbacks.add (mpc.release());
}
else
{
CHECK_ERROR (MIDIPortDispose (port));
}
}
}
}
CFRelease (name);
}
}
return newInput;
}
MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback)
{
jassert (callback != nullptr);
using namespace CoreMidiHelpers;
MidiInput* mi = nullptr;
if (MIDIClientRef client = getGlobalMidiClient())
{
ScopedPointer <MidiPortAndCallback> mpc (new MidiPortAndCallback (*callback));
mpc->active = false;
MIDIEndpointRef endPoint;
CFStringRef name = deviceName.toCFString();
if (CHECK_ERROR (MIDIDestinationCreate (client, name, midiInputProc, mpc, &endPoint)))
{
mpc->portAndEndpoint = new MidiPortAndEndpoint (0, endPoint);
mi = new MidiInput (deviceName);
mpc->input = mi;
mi->internal = mpc;
const ScopedLock sl (callbackLock);
activeCallbacks.add (mpc.release());
}
CFRelease (name);
}
return mi;
}
MidiInput::MidiInput (const String& name_)
: name (name_)
{
}
MidiInput::~MidiInput()
{
delete static_cast<CoreMidiHelpers::MidiPortAndCallback*> (internal);
}
void MidiInput::start()
{
const ScopedLock sl (CoreMidiHelpers::callbackLock);
static_cast<CoreMidiHelpers::MidiPortAndCallback*> (internal)->active = true;
}
void MidiInput::stop()
{
const ScopedLock sl (CoreMidiHelpers::callbackLock);
static_cast<CoreMidiHelpers::MidiPortAndCallback*> (internal)->active = false;
}
#undef CHECK_ERROR

+ 1580
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_ASIO.cpp
File diff suppressed because it is too large
View File


+ 412
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDBurner.cpp View File

@@ -0,0 +1,412 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
namespace CDBurnerHelpers
{
IDiscRecorder* enumCDBurners (StringArray* list, int indexToOpen, IDiscMaster** master)
{
CoInitialize (0);
IDiscMaster* dm;
IDiscRecorder* result = nullptr;
if (SUCCEEDED (CoCreateInstance (CLSID_MSDiscMasterObj, 0,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IDiscMaster,
(void**) &dm)))
{
if (SUCCEEDED (dm->Open()))
{
IEnumDiscRecorders* drEnum = nullptr;
if (SUCCEEDED (dm->EnumDiscRecorders (&drEnum)))
{
IDiscRecorder* dr = nullptr;
DWORD dummy;
int index = 0;
while (drEnum->Next (1, &dr, &dummy) == S_OK)
{
if (indexToOpen == index)
{
result = dr;
break;
}
else if (list != nullptr)
{
BSTR path;
if (SUCCEEDED (dr->GetPath (&path)))
list->add ((const WCHAR*) path);
}
++index;
dr->Release();
}
drEnum->Release();
}
if (master == 0)
dm->Close();
}
if (master != nullptr)
*master = dm;
else
dm->Release();
}
return result;
}
}
//==============================================================================
class AudioCDBurner::Pimpl : public ComBaseClassHelper <IDiscMasterProgressEvents>,
public Timer
{
public:
Pimpl (AudioCDBurner& owner_, IDiscMaster* discMaster_, IDiscRecorder* discRecorder_)
: owner (owner_), discMaster (discMaster_), discRecorder (discRecorder_), redbook (0),
listener (0), progress (0), shouldCancel (false)
{
HRESULT hr = discMaster->SetActiveDiscMasterFormat (IID_IRedbookDiscMaster, (void**) &redbook);
jassert (SUCCEEDED (hr));
hr = discMaster->SetActiveDiscRecorder (discRecorder);
//jassert (SUCCEEDED (hr));
lastState = getDiskState();
startTimer (2000);
}
~Pimpl() {}
void releaseObjects()
{
discRecorder->Close();
if (redbook != nullptr)
redbook->Release();
discRecorder->Release();
discMaster->Release();
Release();
}
JUCE_COMRESULT QueryCancel (boolean* pbCancel)
{
if (listener != nullptr && ! shouldCancel)
shouldCancel = listener->audioCDBurnProgress (progress);
*pbCancel = shouldCancel;
return S_OK;
}
JUCE_COMRESULT NotifyBlockProgress (long nCompleted, long nTotal)
{
progress = nCompleted / (float) nTotal;
shouldCancel = listener != nullptr && listener->audioCDBurnProgress (progress);
return E_NOTIMPL;
}
JUCE_COMRESULT NotifyPnPActivity (void) { return E_NOTIMPL; }
JUCE_COMRESULT NotifyAddProgress (long /*nCompletedSteps*/, long /*nTotalSteps*/) { return E_NOTIMPL; }
JUCE_COMRESULT NotifyTrackProgress (long /*nCurrentTrack*/, long /*nTotalTracks*/) { return E_NOTIMPL; }
JUCE_COMRESULT NotifyPreparingBurn (long /*nEstimatedSeconds*/) { return E_NOTIMPL; }
JUCE_COMRESULT NotifyClosingDisc (long /*nEstimatedSeconds*/) { return E_NOTIMPL; }
JUCE_COMRESULT NotifyBurnComplete (HRESULT /*status*/) { return E_NOTIMPL; }
JUCE_COMRESULT NotifyEraseComplete (HRESULT /*status*/) { return E_NOTIMPL; }
class ScopedDiscOpener
{
public:
ScopedDiscOpener (Pimpl& p) : pimpl (p) { pimpl.discRecorder->OpenExclusive(); }
~ScopedDiscOpener() { pimpl.discRecorder->Close(); }
private:
Pimpl& pimpl;
JUCE_DECLARE_NON_COPYABLE (ScopedDiscOpener)
};
DiskState getDiskState()
{
const ScopedDiscOpener opener (*this);
long type, flags;
HRESULT hr = discRecorder->QueryMediaType (&type, &flags);
if (FAILED (hr))
return unknown;
if (type != 0 && (flags & MEDIA_WRITABLE) != 0)
return writableDiskPresent;
if (type == 0)
return noDisc;
return readOnlyDiskPresent;
}
int getIntProperty (const LPOLESTR name, const int defaultReturn) const
{
ComSmartPtr<IPropertyStorage> prop;
if (FAILED (discRecorder->GetRecorderProperties (prop.resetAndGetPointerAddress())))
return defaultReturn;
PROPSPEC iPropSpec;
iPropSpec.ulKind = PRSPEC_LPWSTR;
iPropSpec.lpwstr = name;
PROPVARIANT iPropVariant;
return FAILED (prop->ReadMultiple (1, &iPropSpec, &iPropVariant))
? defaultReturn : (int) iPropVariant.lVal;
}
bool setIntProperty (const LPOLESTR name, const int value) const
{
ComSmartPtr<IPropertyStorage> prop;
if (FAILED (discRecorder->GetRecorderProperties (prop.resetAndGetPointerAddress())))
return false;
PROPSPEC iPropSpec;
iPropSpec.ulKind = PRSPEC_LPWSTR;
iPropSpec.lpwstr = name;
PROPVARIANT iPropVariant;
if (FAILED (prop->ReadMultiple (1, &iPropSpec, &iPropVariant)))
return false;
iPropVariant.lVal = (long) value;
return SUCCEEDED (prop->WriteMultiple (1, &iPropSpec, &iPropVariant, iPropVariant.vt))
&& SUCCEEDED (discRecorder->SetRecorderProperties (prop));
}
void timerCallback()
{
const DiskState state = getDiskState();
if (state != lastState)
{
lastState = state;
owner.sendChangeMessage();
}
}
AudioCDBurner& owner;
DiskState lastState;
IDiscMaster* discMaster;
IDiscRecorder* discRecorder;
IRedbookDiscMaster* redbook;
AudioCDBurner::BurnProgressListener* listener;
float progress;
bool shouldCancel;
};
//==============================================================================
AudioCDBurner::AudioCDBurner (const int deviceIndex)
{
IDiscMaster* discMaster = nullptr;
IDiscRecorder* discRecorder = CDBurnerHelpers::enumCDBurners (0, deviceIndex, &discMaster);
if (discRecorder != nullptr)
pimpl = new Pimpl (*this, discMaster, discRecorder);
}
AudioCDBurner::~AudioCDBurner()
{
if (pimpl != nullptr)
pimpl.release()->releaseObjects();
}
StringArray AudioCDBurner::findAvailableDevices()
{
StringArray devs;
CDBurnerHelpers::enumCDBurners (&devs, -1, 0);
return devs;
}
AudioCDBurner* AudioCDBurner::openDevice (const int deviceIndex)
{
ScopedPointer<AudioCDBurner> b (new AudioCDBurner (deviceIndex));
if (b->pimpl == 0)
b = nullptr;
return b.release();
}
AudioCDBurner::DiskState AudioCDBurner::getDiskState() const
{
return pimpl->getDiskState();
}
bool AudioCDBurner::isDiskPresent() const
{
return getDiskState() == writableDiskPresent;
}
bool AudioCDBurner::openTray()
{
const Pimpl::ScopedDiscOpener opener (*pimpl);
return SUCCEEDED (pimpl->discRecorder->Eject());
}
AudioCDBurner::DiskState AudioCDBurner::waitUntilStateChange (int timeOutMilliseconds)
{
const int64 timeout = Time::currentTimeMillis() + timeOutMilliseconds;
DiskState oldState = getDiskState();
DiskState newState = oldState;
while (newState == oldState && Time::currentTimeMillis() < timeout)
{
newState = getDiskState();
Thread::sleep (jmin (250, (int) (timeout - Time::currentTimeMillis())));
}
return newState;
}
Array<int> AudioCDBurner::getAvailableWriteSpeeds() const
{
Array<int> results;
const int maxSpeed = pimpl->getIntProperty (L"MaxWriteSpeed", 1);
const int speeds[] = { 1, 2, 4, 8, 12, 16, 20, 24, 32, 40, 64, 80 };
for (int i = 0; i < numElementsInArray (speeds); ++i)
if (speeds[i] <= maxSpeed)
results.add (speeds[i]);
results.addIfNotAlreadyThere (maxSpeed);
return results;
}
bool AudioCDBurner::setBufferUnderrunProtection (const bool shouldBeEnabled)
{
if (pimpl->getIntProperty (L"BufferUnderrunFreeCapable", 0) == 0)
return false;
pimpl->setIntProperty (L"EnableBufferUnderrunFree", shouldBeEnabled ? -1 : 0);
return pimpl->getIntProperty (L"EnableBufferUnderrunFree", 0) != 0;
}
int AudioCDBurner::getNumAvailableAudioBlocks() const
{
long blocksFree = 0;
pimpl->redbook->GetAvailableAudioTrackBlocks (&blocksFree);
return blocksFree;
}
String AudioCDBurner::burn (AudioCDBurner::BurnProgressListener* listener, bool ejectDiscAfterwards,
bool performFakeBurnForTesting, int writeSpeed)
{
pimpl->setIntProperty (L"WriteSpeed", writeSpeed > 0 ? writeSpeed : -1);
pimpl->listener = listener;
pimpl->progress = 0;
pimpl->shouldCancel = false;
UINT_PTR cookie;
HRESULT hr = pimpl->discMaster->ProgressAdvise ((AudioCDBurner::Pimpl*) pimpl, &cookie);
hr = pimpl->discMaster->RecordDisc (performFakeBurnForTesting,
ejectDiscAfterwards);
String error;
if (hr != S_OK)
{
const char* e = "Couldn't open or write to the CD device";
if (hr == IMAPI_E_USERABORT)
e = "User cancelled the write operation";
else if (hr == IMAPI_E_MEDIUM_NOTPRESENT || hr == IMAPI_E_TRACKOPEN)
e = "No Disk present";
error = e;
}
pimpl->discMaster->ProgressUnadvise (cookie);
pimpl->listener = 0;
return error;
}
bool AudioCDBurner::addAudioTrack (AudioSource* audioSource, int numSamples)
{
if (audioSource == 0)
return false;
ScopedPointer<AudioSource> source (audioSource);
long bytesPerBlock;
HRESULT hr = pimpl->redbook->GetAudioBlockSize (&bytesPerBlock);
const int samplesPerBlock = bytesPerBlock / 4;
bool ok = true;
hr = pimpl->redbook->CreateAudioTrack ((long) numSamples / (bytesPerBlock * 4));
HeapBlock <byte> buffer (bytesPerBlock);
AudioSampleBuffer sourceBuffer (2, samplesPerBlock);
int samplesDone = 0;
source->prepareToPlay (samplesPerBlock, 44100.0);
while (ok)
{
{
AudioSourceChannelInfo info (&sourceBuffer, 0, samplesPerBlock);
sourceBuffer.clear();
source->getNextAudioBlock (info);
}
buffer.clear (bytesPerBlock);
typedef AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian,
AudioData::Interleaved, AudioData::NonConst> CDSampleFormat;
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian,
AudioData::NonInterleaved, AudioData::Const> SourceSampleFormat;
CDSampleFormat left (buffer, 2);
left.convertSamples (SourceSampleFormat (sourceBuffer.getSampleData (0)), samplesPerBlock);
CDSampleFormat right (buffer + 2, 2);
right.convertSamples (SourceSampleFormat (sourceBuffer.getSampleData (1)), samplesPerBlock);
hr = pimpl->redbook->AddAudioTrackBlocks (buffer, bytesPerBlock);
if (FAILED (hr))
ok = false;
samplesDone += samplesPerBlock;
if (samplesDone >= numSamples)
break;
}
hr = pimpl->redbook->CloseAudioTrack();
return ok && hr == S_OK;
}

+ 1310
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDReader.cpp
File diff suppressed because it is too large
View File


+ 1290
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp
File diff suppressed because it is too large
View File


+ 482
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_Midi.cpp View File

@@ -0,0 +1,482 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
class MidiInCollector
{
public:
MidiInCollector (MidiInput* const input_,
MidiInputCallback& callback_)
: deviceHandle (0),
input (input_),
callback (callback_),
concatenator (4096),
isStarted (false),
startTime (0)
{
}
~MidiInCollector()
{
stop();
if (deviceHandle != 0)
{
for (int count = 5; --count >= 0;)
{
if (midiInClose (deviceHandle) == MMSYSERR_NOERROR)
break;
Sleep (20);
}
}
}
//==============================================================================
void handleMessage (const uint8* bytes, const uint32 timeStamp)
{
if (bytes[0] >= 0x80 && isStarted)
{
concatenator.pushMidiData (bytes, MidiMessage::getMessageLengthFromFirstByte (bytes[0]),
convertTimeStamp (timeStamp), input, callback);
writeFinishedBlocks();
}
}
void handleSysEx (MIDIHDR* const hdr, const uint32 timeStamp)
{
if (isStarted && hdr->dwBytesRecorded > 0)
{
concatenator.pushMidiData (hdr->lpData, (int) hdr->dwBytesRecorded,
convertTimeStamp (timeStamp), input, callback);
writeFinishedBlocks();
}
}
void start()
{
if (deviceHandle != 0 && ! isStarted)
{
activeMidiCollectors.addIfNotAlreadyThere (this);
for (int i = 0; i < (int) numHeaders; ++i)
headers[i].write (deviceHandle);
startTime = Time::getMillisecondCounterHiRes();
MMRESULT res = midiInStart (deviceHandle);
if (res == MMSYSERR_NOERROR)
{
concatenator.reset();
isStarted = true;
}
else
{
unprepareAllHeaders();
}
}
}
void stop()
{
if (isStarted)
{
isStarted = false;
midiInReset (deviceHandle);
midiInStop (deviceHandle);
activeMidiCollectors.removeFirstMatchingValue (this);
unprepareAllHeaders();
concatenator.reset();
}
}
static void CALLBACK midiInCallback (HMIDIIN, UINT uMsg, DWORD_PTR dwInstance,
DWORD_PTR midiMessage, DWORD_PTR timeStamp)
{
MidiInCollector* const collector = reinterpret_cast <MidiInCollector*> (dwInstance);
if (activeMidiCollectors.contains (collector))
{
if (uMsg == MIM_DATA)
collector->handleMessage ((const uint8*) &midiMessage, (uint32) timeStamp);
else if (uMsg == MIM_LONGDATA)
collector->handleSysEx ((MIDIHDR*) midiMessage, (uint32) timeStamp);
}
}
HMIDIIN deviceHandle;
private:
static Array <MidiInCollector*, CriticalSection> activeMidiCollectors;
MidiInput* input;
MidiInputCallback& callback;
MidiDataConcatenator concatenator;
bool volatile isStarted;
double startTime;
class MidiHeader
{
public:
MidiHeader()
{
zerostruct (hdr);
hdr.lpData = data;
hdr.dwBufferLength = (DWORD) numElementsInArray (data);
}
void write (HMIDIIN deviceHandle)
{
hdr.dwBytesRecorded = 0;
MMRESULT res = midiInPrepareHeader (deviceHandle, &hdr, sizeof (hdr));
res = midiInAddBuffer (deviceHandle, &hdr, sizeof (hdr));
}
void writeIfFinished (HMIDIIN deviceHandle)
{
if ((hdr.dwFlags & WHDR_DONE) != 0)
{
MMRESULT res = midiInUnprepareHeader (deviceHandle, &hdr, sizeof (hdr));
(void) res;
write (deviceHandle);
}
}
void unprepare (HMIDIIN deviceHandle)
{
if ((hdr.dwFlags & WHDR_DONE) != 0)
{
int c = 10;
while (--c >= 0 && midiInUnprepareHeader (deviceHandle, &hdr, sizeof (hdr)) == MIDIERR_STILLPLAYING)
Thread::sleep (20);
jassert (c >= 0);
}
}
private:
MIDIHDR hdr;
char data [256];
JUCE_DECLARE_NON_COPYABLE (MidiHeader)
};
enum { numHeaders = 32 };
MidiHeader headers [numHeaders];
void writeFinishedBlocks()
{
for (int i = 0; i < (int) numHeaders; ++i)
headers[i].writeIfFinished (deviceHandle);
}
void unprepareAllHeaders()
{
for (int i = 0; i < (int) numHeaders; ++i)
headers[i].unprepare (deviceHandle);
}
double convertTimeStamp (uint32 timeStamp)
{
double t = startTime + timeStamp;
const double now = Time::getMillisecondCounterHiRes();
if (t > now)
{
if (t > now + 2.0)
startTime -= 1.0;
t = now;
}
return t * 0.001;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiInCollector)
};
Array <MidiInCollector*, CriticalSection> MidiInCollector::activeMidiCollectors;
//==============================================================================
StringArray MidiInput::getDevices()
{
StringArray s;
const UINT num = midiInGetNumDevs();
for (UINT i = 0; i < num; ++i)
{
MIDIINCAPS mc = { 0 };
if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
s.add (String (mc.szPname, sizeof (mc.szPname)));
}
return s;
}
int MidiInput::getDefaultDeviceIndex()
{
return 0;
}
MidiInput* MidiInput::openDevice (const int index, MidiInputCallback* const callback)
{
if (callback == nullptr)
return nullptr;
UINT deviceId = MIDI_MAPPER;
int n = 0;
String name;
const UINT num = midiInGetNumDevs();
for (UINT i = 0; i < num; ++i)
{
MIDIINCAPS mc = { 0 };
if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
{
if (index == n)
{
deviceId = i;
name = String (mc.szPname, (size_t) numElementsInArray (mc.szPname));
break;
}
++n;
}
}
ScopedPointer <MidiInput> in (new MidiInput (name));
ScopedPointer <MidiInCollector> collector (new MidiInCollector (in, *callback));
HMIDIIN h;
MMRESULT err = midiInOpen (&h, deviceId,
(DWORD_PTR) &MidiInCollector::midiInCallback,
(DWORD_PTR) (MidiInCollector*) collector,
CALLBACK_FUNCTION);
if (err == MMSYSERR_NOERROR)
{
collector->deviceHandle = h;
in->internal = collector.release();
return in.release();
}
return nullptr;
}
MidiInput::MidiInput (const String& name_)
: name (name_),
internal (0)
{
}
MidiInput::~MidiInput()
{
delete static_cast <MidiInCollector*> (internal);
}
void MidiInput::start() { static_cast <MidiInCollector*> (internal)->start(); }
void MidiInput::stop() { static_cast <MidiInCollector*> (internal)->stop(); }
//==============================================================================
struct MidiOutHandle
{
int refCount;
UINT deviceId;
HMIDIOUT handle;
static Array<MidiOutHandle*> activeHandles;
private:
JUCE_LEAK_DETECTOR (MidiOutHandle)
};
Array<MidiOutHandle*> MidiOutHandle::activeHandles;
//==============================================================================
StringArray MidiOutput::getDevices()
{
StringArray s;
const UINT num = midiOutGetNumDevs();
for (UINT i = 0; i < num; ++i)
{
MIDIOUTCAPS mc = { 0 };
if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
s.add (String (mc.szPname, sizeof (mc.szPname)));
}
return s;
}
int MidiOutput::getDefaultDeviceIndex()
{
const UINT num = midiOutGetNumDevs();
int n = 0;
for (UINT i = 0; i < num; ++i)
{
MIDIOUTCAPS mc = { 0 };
if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
{
if ((mc.wTechnology & MOD_MAPPER) != 0)
return n;
++n;
}
}
return 0;
}
MidiOutput* MidiOutput::openDevice (int index)
{
UINT deviceId = MIDI_MAPPER;
const UINT num = midiOutGetNumDevs();
int n = 0;
for (UINT i = 0; i < num; ++i)
{
MIDIOUTCAPS mc = { 0 };
if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
{
// use the microsoft sw synth as a default - best not to allow deviceId
// to be MIDI_MAPPER, or else device sharing breaks
if (String (mc.szPname, sizeof (mc.szPname)).containsIgnoreCase ("microsoft"))
deviceId = i;
if (index == n)
{
deviceId = i;
break;
}
++n;
}
}
for (int i = MidiOutHandle::activeHandles.size(); --i >= 0;)
{
MidiOutHandle* const han = MidiOutHandle::activeHandles.getUnchecked(i);
if (han->deviceId == deviceId)
{
han->refCount++;
MidiOutput* const out = new MidiOutput();
out->internal = han;
return out;
}
}
for (int i = 4; --i >= 0;)
{
HMIDIOUT h = 0;
MMRESULT res = midiOutOpen (&h, deviceId, 0, 0, CALLBACK_NULL);
if (res == MMSYSERR_NOERROR)
{
MidiOutHandle* const han = new MidiOutHandle();
han->deviceId = deviceId;
han->refCount = 1;
han->handle = h;
MidiOutHandle::activeHandles.add (han);
MidiOutput* const out = new MidiOutput();
out->internal = han;
return out;
}
else if (res == MMSYSERR_ALLOCATED)
{
Sleep (100);
}
else
{
break;
}
}
return nullptr;
}
MidiOutput::~MidiOutput()
{
stopBackgroundThread();
MidiOutHandle* const h = static_cast <MidiOutHandle*> (internal);
if (MidiOutHandle::activeHandles.contains (h) && --(h->refCount) == 0)
{
midiOutClose (h->handle);
MidiOutHandle::activeHandles.removeFirstMatchingValue (h);
delete h;
}
}
void MidiOutput::sendMessageNow (const MidiMessage& message)
{
const MidiOutHandle* const handle = static_cast <const MidiOutHandle*> (internal);
if (message.getRawDataSize() > 3 || message.isSysEx())
{
MIDIHDR h = { 0 };
h.lpData = (char*) message.getRawData();
h.dwBytesRecorded = h.dwBufferLength = (DWORD) message.getRawDataSize();
if (midiOutPrepareHeader (handle->handle, &h, sizeof (MIDIHDR)) == MMSYSERR_NOERROR)
{
MMRESULT res = midiOutLongMsg (handle->handle, &h, sizeof (MIDIHDR));
if (res == MMSYSERR_NOERROR)
{
while ((h.dwFlags & MHDR_DONE) == 0)
Sleep (1);
int count = 500; // 1 sec timeout
while (--count >= 0)
{
res = midiOutUnprepareHeader (handle->handle, &h, sizeof (MIDIHDR));
if (res == MIDIERR_STILLPLAYING)
Sleep (2);
else
break;
}
}
}
}
else
{
midiOutShortMsg (handle->handle, *(unsigned int*) message.getRawData());
}
}

+ 1226
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp
File diff suppressed because it is too large
View File


+ 184
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp View File

@@ -0,0 +1,184 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
AudioSourcePlayer::AudioSourcePlayer()
: source (nullptr),
sampleRate (0),
bufferSize (0),
tempBuffer (2, 8),
lastGain (1.0f),
gain (1.0f)
{
}
AudioSourcePlayer::~AudioSourcePlayer()
{
setSource (nullptr);
}
void AudioSourcePlayer::setSource (AudioSource* newSource)
{
if (source != newSource)
{
AudioSource* const oldSource = source;
if (newSource != nullptr && bufferSize > 0 && sampleRate > 0)
newSource->prepareToPlay (bufferSize, sampleRate);
{
const ScopedLock sl (readLock);
source = newSource;
}
if (oldSource != nullptr)
oldSource->releaseResources();
}
}
void AudioSourcePlayer::setGain (const float newGain) noexcept
{
gain = newGain;
}
void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData,
int totalNumInputChannels,
float** outputChannelData,
int totalNumOutputChannels,
int numSamples)
{
// these should have been prepared by audioDeviceAboutToStart()...
jassert (sampleRate > 0 && bufferSize > 0);
const ScopedLock sl (readLock);
if (source != nullptr)
{
int numActiveChans = 0, numInputs = 0, numOutputs = 0;
// messy stuff needed to compact the channels down into an array
// of non-zero pointers..
for (int i = 0; i < totalNumInputChannels; ++i)
{
if (inputChannelData[i] != nullptr)
{
inputChans [numInputs++] = inputChannelData[i];
if (numInputs >= numElementsInArray (inputChans))
break;
}
}
for (int i = 0; i < totalNumOutputChannels; ++i)
{
if (outputChannelData[i] != nullptr)
{
outputChans [numOutputs++] = outputChannelData[i];
if (numOutputs >= numElementsInArray (outputChans))
break;
}
}
if (numInputs > numOutputs)
{
// if there aren't enough output channels for the number of
// inputs, we need to create some temporary extra ones (can't
// use the input data in case it gets written to)
tempBuffer.setSize (numInputs - numOutputs, numSamples,
false, false, true);
for (int i = 0; i < numOutputs; ++i)
{
channels[numActiveChans] = outputChans[i];
memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples);
++numActiveChans;
}
for (int i = numOutputs; i < numInputs; ++i)
{
channels[numActiveChans] = tempBuffer.getSampleData (i - numOutputs, 0);
memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples);
++numActiveChans;
}
}
else
{
for (int i = 0; i < numInputs; ++i)
{
channels[numActiveChans] = outputChans[i];
memcpy (channels[numActiveChans], inputChans[i], sizeof (float) * (size_t) numSamples);
++numActiveChans;
}
for (int i = numInputs; i < numOutputs; ++i)
{
channels[numActiveChans] = outputChans[i];
zeromem (channels[numActiveChans], sizeof (float) * (size_t) numSamples);
++numActiveChans;
}
}
AudioSampleBuffer buffer (channels, numActiveChans, numSamples);
AudioSourceChannelInfo info (&buffer, 0, numSamples);
source->getNextAudioBlock (info);
for (int i = info.buffer->getNumChannels(); --i >= 0;)
buffer.applyGainRamp (i, info.startSample, info.numSamples, lastGain, gain);
lastGain = gain;
}
else
{
for (int i = 0; i < totalNumOutputChannels; ++i)
if (outputChannelData[i] != nullptr)
zeromem (outputChannelData[i], sizeof (float) * (size_t) numSamples);
}
}
void AudioSourcePlayer::audioDeviceAboutToStart (AudioIODevice* device)
{
prepareToPlay (device->getCurrentSampleRate(),
device->getCurrentBufferSizeSamples());
}
void AudioSourcePlayer::prepareToPlay (double newSampleRate, int newBufferSize)
{
sampleRate = newSampleRate;
bufferSize = newBufferSize;
zeromem (channels, sizeof (channels));
if (source != nullptr)
source->prepareToPlay (bufferSize, sampleRate);
}
void AudioSourcePlayer::audioDeviceStopped()
{
if (source != nullptr)
source->releaseResources();
sampleRate = 0.0;
bufferSize = 0;
tempBuffer.setSize (2, 8);
}

+ 117
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h View File

@@ -0,0 +1,117 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOSOURCEPLAYER_JUCEHEADER__
#define __JUCE_AUDIOSOURCEPLAYER_JUCEHEADER__
//==============================================================================
/**
Wrapper class to continuously stream audio from an audio source to an
AudioIODevice.
This object acts as an AudioIODeviceCallback, so can be attached to an
output device, and will stream audio from an AudioSource.
*/
class JUCE_API AudioSourcePlayer : public AudioIODeviceCallback
{
public:
//==============================================================================
/** Creates an empty AudioSourcePlayer. */
AudioSourcePlayer();
/** Destructor.
Make sure this object isn't still being used by an AudioIODevice before
deleting it!
*/
virtual ~AudioSourcePlayer();
//==============================================================================
/** Changes the current audio source to play from.
If the source passed in is already being used, this method will do nothing.
If the source is not null, its prepareToPlay() method will be called
before it starts being used for playback.
If there's another source currently playing, its releaseResources() method
will be called after it has been swapped for the new one.
@param newSource the new source to use - this will NOT be deleted
by this object when no longer needed, so it's the
caller's responsibility to manage it.
*/
void setSource (AudioSource* newSource);
/** Returns the source that's playing.
May return 0 if there's no source.
*/
AudioSource* getCurrentSource() const noexcept { return source; }
/** Sets a gain to apply to the audio data.
@see getGain
*/
void setGain (float newGain) noexcept;
/** Returns the current gain.
@see setGain
*/
float getGain() const noexcept { return gain; }
//==============================================================================
/** Implementation of the AudioIODeviceCallback method. */
void audioDeviceIOCallback (const float** inputChannelData,
int totalNumInputChannels,
float** outputChannelData,
int totalNumOutputChannels,
int numSamples);
/** Implementation of the AudioIODeviceCallback method. */
void audioDeviceAboutToStart (AudioIODevice* device);
/** Implementation of the AudioIODeviceCallback method. */
void audioDeviceStopped();
/** An alternative method for initialising the source without an AudioIODevice. */
void prepareToPlay (double sampleRate, int blockSize);
private:
//==============================================================================
CriticalSection readLock;
AudioSource* source;
double sampleRate;
int bufferSize;
float* channels [128];
float* outputChans [128];
const float* inputChans [128];
AudioSampleBuffer tempBuffer;
float lastGain, gain;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioSourcePlayer)
};
#endif // __JUCE_AUDIOSOURCEPLAYER_JUCEHEADER__

+ 302
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp View File

@@ -0,0 +1,302 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
AudioTransportSource::AudioTransportSource()
: source (nullptr),
resamplerSource (nullptr),
bufferingSource (nullptr),
positionableSource (nullptr),
masterSource (nullptr),
gain (1.0f),
lastGain (1.0f),
playing (false),
stopped (true),
sampleRate (44100.0),
sourceSampleRate (0.0),
blockSize (128),
readAheadBufferSize (0),
isPrepared (false),
inputStreamEOF (false)
{
}
AudioTransportSource::~AudioTransportSource()
{
setSource (nullptr);
releaseMasterResources();
}
void AudioTransportSource::setSource (PositionableAudioSource* const newSource,
int readAheadBufferSize_,
TimeSliceThread* readAheadThread,
double sourceSampleRateToCorrectFor,
int maxNumChannels)
{
if (source == newSource)
{
if (source == nullptr)
return;
setSource (nullptr, 0, nullptr); // deselect and reselect to avoid releasing resources wrongly
}
readAheadBufferSize = readAheadBufferSize_;
sourceSampleRate = sourceSampleRateToCorrectFor;
ResamplingAudioSource* newResamplerSource = nullptr;
BufferingAudioSource* newBufferingSource = nullptr;
PositionableAudioSource* newPositionableSource = nullptr;
AudioSource* newMasterSource = nullptr;
ScopedPointer <ResamplingAudioSource> oldResamplerSource (resamplerSource);
ScopedPointer <BufferingAudioSource> oldBufferingSource (bufferingSource);
AudioSource* oldMasterSource = masterSource;
if (newSource != nullptr)
{
newPositionableSource = newSource;
if (readAheadBufferSize_ > 0)
{
// If you want to use a read-ahead buffer, you must also provide a TimeSliceThread
// for it to use!
jassert (readAheadThread != nullptr);
newPositionableSource = newBufferingSource
= new BufferingAudioSource (newPositionableSource, *readAheadThread,
false, readAheadBufferSize_, maxNumChannels);
}
newPositionableSource->setNextReadPosition (0);
if (sourceSampleRateToCorrectFor > 0)
newMasterSource = newResamplerSource
= new ResamplingAudioSource (newPositionableSource, false, maxNumChannels);
else
newMasterSource = newPositionableSource;
if (isPrepared)
{
if (newResamplerSource != nullptr && sourceSampleRate > 0 && sampleRate > 0)
newResamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
newMasterSource->prepareToPlay (blockSize, sampleRate);
}
}
{
const ScopedLock sl (callbackLock);
source = newSource;
resamplerSource = newResamplerSource;
bufferingSource = newBufferingSource;
masterSource = newMasterSource;
positionableSource = newPositionableSource;
playing = false;
}
if (oldMasterSource != nullptr)
oldMasterSource->releaseResources();
}
void AudioTransportSource::start()
{
if ((! playing) && masterSource != nullptr)
{
{
const ScopedLock sl (callbackLock);
playing = true;
stopped = false;
inputStreamEOF = false;
}
sendChangeMessage();
}
}
void AudioTransportSource::stop()
{
if (playing)
{
{
const ScopedLock sl (callbackLock);
playing = false;
}
int n = 500;
while (--n >= 0 && ! stopped)
Thread::sleep (2);
sendChangeMessage();
}
}
void AudioTransportSource::setPosition (double newPosition)
{
if (sampleRate > 0.0)
setNextReadPosition ((int64) (newPosition * sampleRate));
}
double AudioTransportSource::getCurrentPosition() const
{
if (sampleRate > 0.0)
return getNextReadPosition() / sampleRate;
return 0.0;
}
double AudioTransportSource::getLengthInSeconds() const
{
return getTotalLength() / sampleRate;
}
void AudioTransportSource::setNextReadPosition (int64 newPosition)
{
if (positionableSource != nullptr)
{
if (sampleRate > 0 && sourceSampleRate > 0)
newPosition = (int64) (newPosition * sourceSampleRate / sampleRate);
positionableSource->setNextReadPosition (newPosition);
}
}
int64 AudioTransportSource::getNextReadPosition() const
{
if (positionableSource != nullptr)
{
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
return (int64) (positionableSource->getNextReadPosition() * ratio);
}
return 0;
}
int64 AudioTransportSource::getTotalLength() const
{
const ScopedLock sl (callbackLock);
if (positionableSource != nullptr)
{
const double ratio = (sampleRate > 0 && sourceSampleRate > 0) ? sampleRate / sourceSampleRate : 1.0;
return (int64) (positionableSource->getTotalLength() * ratio);
}
return 0;
}
bool AudioTransportSource::isLooping() const
{
const ScopedLock sl (callbackLock);
return positionableSource != nullptr
&& positionableSource->isLooping();
}
void AudioTransportSource::setGain (const float newGain) noexcept
{
gain = newGain;
}
void AudioTransportSource::prepareToPlay (int samplesPerBlockExpected,
double sampleRate_)
{
const ScopedLock sl (callbackLock);
sampleRate = sampleRate_;
blockSize = samplesPerBlockExpected;
if (masterSource != nullptr)
masterSource->prepareToPlay (samplesPerBlockExpected, sampleRate);
if (resamplerSource != nullptr && sourceSampleRate > 0)
resamplerSource->setResamplingRatio (sourceSampleRate / sampleRate);
isPrepared = true;
}
void AudioTransportSource::releaseMasterResources()
{
const ScopedLock sl (callbackLock);
if (masterSource != nullptr)
masterSource->releaseResources();
isPrepared = false;
}
void AudioTransportSource::releaseResources()
{
releaseMasterResources();
}
void AudioTransportSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{
const ScopedLock sl (callbackLock);
inputStreamEOF = false;
if (masterSource != nullptr && ! stopped)
{
masterSource->getNextAudioBlock (info);
if (! playing)
{
// just stopped playing, so fade out the last block..
for (int i = info.buffer->getNumChannels(); --i >= 0;)
info.buffer->applyGainRamp (i, info.startSample, jmin (256, info.numSamples), 1.0f, 0.0f);
if (info.numSamples > 256)
info.buffer->clear (info.startSample + 256, info.numSamples - 256);
}
if (positionableSource->getNextReadPosition() > positionableSource->getTotalLength() + 1
&& ! positionableSource->isLooping())
{
playing = false;
inputStreamEOF = true;
sendChangeMessage();
}
stopped = ! playing;
for (int i = info.buffer->getNumChannels(); --i >= 0;)
{
info.buffer->applyGainRamp (i, info.startSample, info.numSamples,
lastGain, gain);
}
}
else
{
info.clearActiveBufferRegion();
stopped = true;
}
lastGain = gain;
}

+ 187
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.h View File

@@ -0,0 +1,187 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-11 by Raw Material Software Ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the GNU General
Public License (Version 2), as published by the Free Software Foundation.
A copy of the license is included in the JUCE distribution, or can be found
online at www.gnu.org/licenses.
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.rawmaterialsoftware.com/juce for more information.
==============================================================================
*/
#ifndef __JUCE_AUDIOTRANSPORTSOURCE_JUCEHEADER__
#define __JUCE_AUDIOTRANSPORTSOURCE_JUCEHEADER__
//==============================================================================
/**
An AudioSource that takes a PositionableAudioSource and allows it to be
played, stopped, started, etc.
This can also be told use a buffer and background thread to read ahead, and
if can correct for different sample-rates.
You may want to use one of these along with an AudioSourcePlayer and AudioIODevice
to control playback of an audio file.
@see AudioSource, AudioSourcePlayer
*/
class JUCE_API AudioTransportSource : public PositionableAudioSource,
public ChangeBroadcaster
{
public:
//==============================================================================
/** Creates an AudioTransportSource.
After creating one of these, use the setSource() method to select an input source.
*/
AudioTransportSource();
/** Destructor. */
~AudioTransportSource();
//==============================================================================
/** Sets the reader that is being used as the input source.
This will stop playback, reset the position to 0 and change to the new reader.
The source passed in will not be deleted by this object, so must be managed by
the caller.
@param newSource the new input source to use. This may be zero
@param readAheadBufferSize a size of buffer to use for reading ahead. If this
is zero, no reading ahead will be done; if it's
greater than zero, a BufferingAudioSource will be used
to do the reading-ahead. If you set a non-zero value here,
you'll also need to set the readAheadThread parameter.
@param readAheadThread if you set readAheadBufferSize to a non-zero value, then
you'll also need to supply this TimeSliceThread object for
the background reader to use. The thread object must not be
deleted while the AudioTransport source is still using it.
@param sourceSampleRateToCorrectFor if this is non-zero, it specifies the sample
rate of the source, and playback will be sample-rate
adjusted to maintain playback at the correct pitch. If
this is 0, no sample-rate adjustment will be performed
@param maxNumChannels the maximum number of channels that may need to be played
*/
void setSource (PositionableAudioSource* newSource,
int readAheadBufferSize = 0,
TimeSliceThread* readAheadThread = nullptr,
double sourceSampleRateToCorrectFor = 0.0,
int maxNumChannels = 2);
//==============================================================================
/** Changes the current playback position in the source stream.
The next time the getNextAudioBlock() method is called, this
is the time from which it'll read data.
@see getPosition
*/
void setPosition (double newPosition);
/** Returns the position that the next data block will be read from
This is a time in seconds.
*/
double getCurrentPosition() const;
/** Returns the stream's length in seconds. */
double getLengthInSeconds() const;
/** Returns true if the player has stopped because its input stream ran out of data.
*/
bool hasStreamFinished() const noexcept { return inputStreamEOF; }
//==============================================================================
/** Starts playing (if a source has been selected).
If it starts playing, this will send a message to any ChangeListeners
that are registered with this object.
*/
void start();
/** Stops playing.
If it's actually playing, this will send a message to any ChangeListeners
that are registered with this object.
*/
void stop();
/** Returns true if it's currently playing. */
bool isPlaying() const noexcept { return playing; }
//==============================================================================
/** Changes the gain to apply to the output.
@param newGain a factor by which to multiply the outgoing samples,
so 1.0 = 0dB, 0.5 = -6dB, 2.0 = 6dB, etc.
*/
void setGain (float newGain) noexcept;
/** Returns the current gain setting.
@see setGain
*/
float getGain() const noexcept { return gain; }
//==============================================================================
/** Implementation of the AudioSource method. */
void prepareToPlay (int samplesPerBlockExpected, double sampleRate);
/** Implementation of the AudioSource method. */
void releaseResources();
/** Implementation of the AudioSource method. */
void getNextAudioBlock (const AudioSourceChannelInfo& bufferToFill);
//==============================================================================
/** Implements the PositionableAudioSource method. */
void setNextReadPosition (int64 newPosition);
/** Implements the PositionableAudioSource method. */
int64 getNextReadPosition() const;
/** Implements the PositionableAudioSource method. */
int64 getTotalLength() const;
/** Implements the PositionableAudioSource method. */
bool isLooping() const;
private:
//==============================================================================
PositionableAudioSource* source;
ResamplingAudioSource* resamplerSource;
BufferingAudioSource* bufferingSource;
PositionableAudioSource* positionableSource;
AudioSource* masterSource;
CriticalSection callbackLock;
float volatile gain, lastGain;
bool volatile playing, stopped;
double sampleRate, sourceSampleRate;
int blockSize, readAheadBufferSize;
bool isPrepared, inputStreamEOF;
void releaseMasterResources();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioTransportSource)
};
#endif // __JUCE_AUDIOTRANSPORTSOURCE_JUCEHEADER__

+ 49
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/Flac Licence.txt View File

@@ -0,0 +1,49 @@

=====================================================================

I've incorporated FLAC directly into the Juce codebase because it makes
things much easier than having to make all your builds link correctly to
the appropriate libraries on every different platform.

I've made minimal changes to the FLAC code - just tweaked a few include paths
to make it build smoothly, added some headers to allow you to turn off FLAC
compilation, and commented-out a couple of unused bits of code.

=====================================================================


The following license is the BSD-style license that comes with the
Flac distribution, and which applies just to the files I've
included in this directory. For more info, and to get the rest of the
distribution, visit the Flac homepage: flac.sourceforge.net

=====================================================================

Copyright (C) 2000,2001,2002,2003,2004,2005,2006 Josh Coalson

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.

- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.

- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 402
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/all.h View File

@@ -0,0 +1,402 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FLAC__ALL_H
#define FLAC__ALL_H
#include "export.h"
#include "assert.h"
#include "callback.h"
#include "format.h"
#include "metadata.h"
#include "ordinals.h"
#include "stream_decoder.h"
#include "stream_encoder.h"
#ifdef _MSC_VER
/* OPT: an MSVC built-in would be better */
static _inline FLAC__uint32 local_swap32_(FLAC__uint32 x)
{
x = ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF);
return (x>>16) | (x<<16);
}
#endif
#if defined(_MSC_VER) && defined(_X86_)
/* OPT: an MSVC built-in would be better */
static void local_swap32_block_(FLAC__uint32 *start, FLAC__uint32 len)
{
__asm {
mov edx, start
mov ecx, len
test ecx, ecx
loop1:
jz done1
mov eax, [edx]
bswap eax
mov [edx], eax
add edx, 4
dec ecx
jmp short loop1
done1:
}
}
#endif
/** \mainpage
*
* \section intro Introduction
*
* This is the documentation for the FLAC C and C++ APIs. It is
* highly interconnected; this introduction should give you a top
* level idea of the structure and how to find the information you
* need. As a prerequisite you should have at least a basic
* knowledge of the FLAC format, documented
* <A HREF="../format.html">here</A>.
*
* \section c_api FLAC C API
*
* The FLAC C API is the interface to libFLAC, a set of structures
* describing the components of FLAC streams, and functions for
* encoding and decoding streams, as well as manipulating FLAC
* metadata in files. The public include files will be installed
* in your include area (for example /usr/include/FLAC/...).
*
* By writing a little code and linking against libFLAC, it is
* relatively easy to add FLAC support to another program. The
* library is licensed under <A HREF="../license.html">Xiph's BSD license</A>.
* Complete source code of libFLAC as well as the command-line
* encoder and plugins is available and is a useful source of
* examples.
*
* Aside from encoders and decoders, libFLAC provides a powerful
* metadata interface for manipulating metadata in FLAC files. It
* allows the user to add, delete, and modify FLAC metadata blocks
* and it can automatically take advantage of PADDING blocks to avoid
* rewriting the entire FLAC file when changing the size of the
* metadata.
*
* libFLAC usually only requires the standard C library and C math
* library. In particular, threading is not used so there is no
* dependency on a thread library. However, libFLAC does not use
* global variables and should be thread-safe.
*
* libFLAC also supports encoding to and decoding from Ogg FLAC.
* However the metadata editing interfaces currently have limited
* read-only support for Ogg FLAC files.
*
* \section cpp_api FLAC C++ API
*
* The FLAC C++ API is a set of classes that encapsulate the
* structures and functions in libFLAC. They provide slightly more
* functionality with respect to metadata but are otherwise
* equivalent. For the most part, they share the same usage as
* their counterparts in libFLAC, and the FLAC C API documentation
* can be used as a supplement. The public include files
* for the C++ API will be installed in your include area (for
* example /usr/include/FLAC++/...).
*
* libFLAC++ is also licensed under
* <A HREF="../license.html">Xiph's BSD license</A>.
*
* \section getting_started Getting Started
*
* A good starting point for learning the API is to browse through
* the <A HREF="modules.html">modules</A>. Modules are logical
* groupings of related functions or classes, which correspond roughly
* to header files or sections of header files. Each module includes a
* detailed description of the general usage of its functions or
* classes.
*
* From there you can go on to look at the documentation of
* individual functions. You can see different views of the individual
* functions through the links in top bar across this page.
*
* If you prefer a more hands-on approach, you can jump right to some
* <A HREF="../documentation_example_code.html">example code</A>.
*
* \section porting_guide Porting Guide
*
* Starting with FLAC 1.1.3 a \link porting Porting Guide \endlink
* has been introduced which gives detailed instructions on how to
* port your code to newer versions of FLAC.
*
* \section embedded_developers Embedded Developers
*
* libFLAC has grown larger over time as more functionality has been
* included, but much of it may be unnecessary for a particular embedded
* implementation. Unused parts may be pruned by some simple editing of
* src/libFLAC/Makefile.am. In general, the decoders, encoders, and
* metadata interface are all independent from each other.
*
* It is easiest to just describe the dependencies:
*
* - All modules depend on the \link flac_format Format \endlink module.
* - The decoders and encoders depend on the bitbuffer.
* - The decoder is independent of the encoder. The encoder uses the
* decoder because of the verify feature, but this can be removed if
* not needed.
* - Parts of the metadata interface require the stream decoder (but not
* the encoder).
* - Ogg support is selectable through the compile time macro
* \c FLAC__HAS_OGG.
*
* For example, if your application only requires the stream decoder, no
* encoder, and no metadata interface, you can remove the stream encoder
* and the metadata interface, which will greatly reduce the size of the
* library.
*
* Also, there are several places in the libFLAC code with comments marked
* with "OPT:" where a #define can be changed to enable code that might be
* faster on a specific platform. Experimenting with these can yield faster
* binaries.
*/
/** \defgroup porting Porting Guide for New Versions
*
* This module describes differences in the library interfaces from
* version to version. It assists in the porting of code that uses
* the libraries to newer versions of FLAC.
*
* One simple facility for making porting easier that has been added
* in FLAC 1.1.3 is a set of \c #defines in \c export.h of each
* library's includes (e.g. \c include/FLAC/export.h). The
* \c #defines mirror the libraries'
* <A HREF="http://www.gnu.org/software/libtool/manual.html#Libtool-versioning">libtool version numbers</A>,
* e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT,
* \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE.
* These can be used to support multiple versions of an API during the
* transition phase, e.g.
*
* \code
* #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
* legacy code
* #else
* new code
* #endif
* \endcode
*
* The the source will work for multiple versions and the legacy code can
* easily be removed when the transition is complete.
*
* Another available symbol is FLAC_API_SUPPORTS_OGG_FLAC (defined in
* include/FLAC/export.h), which can be used to determine whether or not
* the library has been compiled with support for Ogg FLAC. This is
* simpler than trying to call an Ogg init function and catching the
* error.
*/
/** \defgroup porting_1_1_2_to_1_1_3 Porting from FLAC 1.1.2 to 1.1.3
* \ingroup porting
*
* \brief
* This module describes porting from FLAC 1.1.2 to FLAC 1.1.3.
*
* The main change between the APIs in 1.1.2 and 1.1.3 is that they have
* been simplified. First, libOggFLAC has been merged into libFLAC and
* libOggFLAC++ has been merged into libFLAC++. Second, both the three
* decoding layers and three encoding layers have been merged into a
* single stream decoder and stream encoder. That is, the functionality
* of FLAC__SeekableStreamDecoder and FLAC__FileDecoder has been merged
* into FLAC__StreamDecoder, and FLAC__SeekableStreamEncoder and
* FLAC__FileEncoder into FLAC__StreamEncoder. Only the
* FLAC__StreamDecoder and FLAC__StreamEncoder remain. What this means
* is there is now a single API that can be used to encode or decode
* streams to/from native FLAC or Ogg FLAC and the single API can work
* on both seekable and non-seekable streams.
*
* Instead of creating an encoder or decoder of a certain layer, now the
* client will always create a FLAC__StreamEncoder or
* FLAC__StreamDecoder. The old layers are now differentiated by the
* initialization function. For example, for the decoder,
* FLAC__stream_decoder_init() has been replaced by
* FLAC__stream_decoder_init_stream(). This init function takes
* callbacks for the I/O, and the seeking callbacks are optional. This
* allows the client to use the same object for seekable and
* non-seekable streams. For decoding a FLAC file directly, the client
* can use FLAC__stream_decoder_init_file() and pass just a filename
* and fewer callbacks; most of the other callbacks are supplied
* internally. For situations where fopen()ing by filename is not
* possible (e.g. Unicode filenames on Windows) the client can instead
* open the file itself and supply the FILE* to
* FLAC__stream_decoder_init_FILE(). The init functions now returns a
* FLAC__StreamDecoderInitStatus instead of FLAC__StreamDecoderState.
* Since the callbacks and client data are now passed to the init
* function, the FLAC__stream_decoder_set_*_callback() functions and
* FLAC__stream_decoder_set_client_data() are no longer needed. The
* rest of the calls to the decoder are the same as before.
*
* There are counterpart init functions for Ogg FLAC, e.g.
* FLAC__stream_decoder_init_ogg_stream(). All the rest of the calls
* and callbacks are the same as for native FLAC.
*
* As an example, in FLAC 1.1.2 a seekable stream decoder would have
* been set up like so:
*
* \code
* FLAC__SeekableStreamDecoder *decoder = FLAC__seekable_stream_decoder_new();
* if(decoder == NULL) do_something;
* FLAC__seekable_stream_decoder_set_md5_checking(decoder, true);
* [... other settings ...]
* FLAC__seekable_stream_decoder_set_read_callback(decoder, my_read_callback);
* FLAC__seekable_stream_decoder_set_seek_callback(decoder, my_seek_callback);
* FLAC__seekable_stream_decoder_set_tell_callback(decoder, my_tell_callback);
* FLAC__seekable_stream_decoder_set_length_callback(decoder, my_length_callback);
* FLAC__seekable_stream_decoder_set_eof_callback(decoder, my_eof_callback);
* FLAC__seekable_stream_decoder_set_write_callback(decoder, my_write_callback);
* FLAC__seekable_stream_decoder_set_metadata_callback(decoder, my_metadata_callback);
* FLAC__seekable_stream_decoder_set_error_callback(decoder, my_error_callback);
* FLAC__seekable_stream_decoder_set_client_data(decoder, my_client_data);
* if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) do_something;
* \endcode
*
* In FLAC 1.1.3 it is like this:
*
* \code
* FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new();
* if(decoder == NULL) do_something;
* FLAC__stream_decoder_set_md5_checking(decoder, true);
* [... other settings ...]
* if(FLAC__stream_decoder_init_stream(
* decoder,
* my_read_callback,
* my_seek_callback, // or NULL
* my_tell_callback, // or NULL
* my_length_callback, // or NULL
* my_eof_callback, // or NULL
* my_write_callback,
* my_metadata_callback, // or NULL
* my_error_callback,
* my_client_data
* ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something;
* \endcode
*
* or you could do;
*
* \code
* [...]
* FILE *file = fopen("somefile.flac","rb");
* if(file == NULL) do_somthing;
* if(FLAC__stream_decoder_init_FILE(
* decoder,
* file,
* my_write_callback,
* my_metadata_callback, // or NULL
* my_error_callback,
* my_client_data
* ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something;
* \endcode
*
* or just:
*
* \code
* [...]
* if(FLAC__stream_decoder_init_file(
* decoder,
* "somefile.flac",
* my_write_callback,
* my_metadata_callback, // or NULL
* my_error_callback,
* my_client_data
* ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something;
* \endcode
*
* Another small change to the decoder is in how it handles unparseable
* streams. Before, when the decoder found an unparseable stream
* (reserved for when the decoder encounters a stream from a future
* encoder that it can't parse), it changed the state to
* \c FLAC__STREAM_DECODER_UNPARSEABLE_STREAM. Now the decoder instead
* drops sync and calls the error callback with a new error code
* \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM. This is
* more robust. If your error callback does not discriminate on the the
* error state, your code does not need to be changed.
*
* The encoder now has a new setting:
* FLAC__stream_encoder_set_apodization(). This is for setting the
* method used to window the data before LPC analysis. You only need to
* add a call to this function if the default is not suitable. There
* are also two new convenience functions that may be useful:
* FLAC__metadata_object_cuesheet_calculate_cddb_id() and
* FLAC__metadata_get_cuesheet().
*
* The \a bytes parameter to FLAC__StreamDecoderReadCallback,
* FLAC__StreamEncoderReadCallback, and FLAC__StreamEncoderWriteCallback
* is now \c size_t instead of \c unsigned.
*/
/** \defgroup porting_1_1_3_to_1_1_4 Porting from FLAC 1.1.3 to 1.1.4
* \ingroup porting
*
* \brief
* This module describes porting from FLAC 1.1.3 to FLAC 1.1.4.
*
* There were no changes to any of the interfaces from 1.1.3 to 1.1.4.
* There was a slight change in the implementation of
* FLAC__stream_encoder_set_metadata(); the function now makes a copy
* of the \a metadata array of pointers so the client no longer needs
* to maintain it after the call. The objects themselves that are
* pointed to by the array are still not copied though and must be
* maintained until the call to FLAC__stream_encoder_finish().
*/
/** \defgroup porting_1_1_4_to_1_2_0 Porting from FLAC 1.1.4 to 1.2.0
* \ingroup porting
*
* \brief
* This module describes porting from FLAC 1.1.4 to FLAC 1.2.0.
*
* There were only very minor changes to the interfaces from 1.1.4 to 1.2.0.
* In libFLAC, \c FLAC__format_sample_rate_is_subset() was added.
* In libFLAC++, \c FLAC::Decoder::Stream::get_decode_position() was added.
*
* Finally, value of the constant \c FLAC__FRAME_HEADER_RESERVED_LEN
* has changed to reflect the conversion of one of the reserved bits
* into active use. It used to be \c 2 and now is \c 1. However the
* FLAC frame header length has not changed, so to skip the proper
* number of bits, use \c FLAC__FRAME_HEADER_RESERVED_LEN +
* \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN
*/
/** \defgroup flac FLAC C API
*
* The FLAC C API is the interface to libFLAC, a set of structures
* describing the components of FLAC streams, and functions for
* encoding and decoding streams, as well as manipulating FLAC
* metadata in files.
*
* You should start with the format components as all other modules
* are dependent on it.
*/
#endif

+ 212
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/alloc.h View File

@@ -0,0 +1,212 @@
/* alloc - Convenience routines for safely allocating memory
* Copyright (C) 2007 Josh Coalson
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef FLAC__SHARE__ALLOC_H
#define FLAC__SHARE__ALLOC_H
#if HAVE_CONFIG_H
# include <config.h>
#endif
/* WATCHOUT: for c++ you may have to #define __STDC_LIMIT_MACROS 1 real early
* before #including this file, otherwise SIZE_MAX might not be defined
*/
#include <limits.h> /* for SIZE_MAX */
#if !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
#include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */
#endif
#include <stdlib.h> /* for size_t, malloc(), etc */
#ifndef SIZE_MAX
# ifndef SIZE_T_MAX
# ifdef _MSC_VER
# define SIZE_T_MAX UINT_MAX
# else
# error
# endif
# endif
# define SIZE_MAX SIZE_T_MAX
#endif
#ifndef FLaC__INLINE
#define FLaC__INLINE
#endif
/* avoid malloc()ing 0 bytes, see:
* https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003
*/
static FLaC__INLINE void *safe_malloc_(size_t size)
{
/* malloc(0) is undefined; FLAC src convention is to always allocate */
if(!size)
size++;
return malloc(size);
}
static FLaC__INLINE void *safe_calloc_(size_t nmemb, size_t size)
{
if(!nmemb || !size)
return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
return calloc(nmemb, size);
}
/*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */
static FLaC__INLINE void *safe_malloc_add_2op_(size_t size1, size_t size2)
{
size2 += size1;
if(size2 < size1)
return 0;
return safe_malloc_(size2);
}
static FLaC__INLINE void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3)
{
size2 += size1;
if(size2 < size1)
return 0;
size3 += size2;
if(size3 < size2)
return 0;
return safe_malloc_(size3);
}
static FLaC__INLINE void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4)
{
size2 += size1;
if(size2 < size1)
return 0;
size3 += size2;
if(size3 < size2)
return 0;
size4 += size3;
if(size4 < size3)
return 0;
return safe_malloc_(size4);
}
static FLaC__INLINE void *safe_malloc_mul_2op_(size_t size1, size_t size2)
#if 0
needs support for cases where sizeof(size_t) != 4
{
/* could be faster #ifdef'ing off SIZEOF_SIZE_T */
if(sizeof(size_t) == 4) {
if ((double)size1 * (double)size2 < 4294967296.0)
return malloc(size1*size2);
}
return 0;
}
#else
/* better? */
{
if(!size1 || !size2)
return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
if(size1 > SIZE_MAX / size2)
return 0;
return malloc(size1*size2);
}
#endif
static FLaC__INLINE void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3)
{
if(!size1 || !size2 || !size3)
return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
if(size1 > SIZE_MAX / size2)
return 0;
size1 *= size2;
if(size1 > SIZE_MAX / size3)
return 0;
return malloc(size1*size3);
}
/* size1*size2 + size3 */
static FLaC__INLINE void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3)
{
if(!size1 || !size2)
return safe_malloc_(size3);
if(size1 > SIZE_MAX / size2)
return 0;
return safe_malloc_add_2op_(size1*size2, size3);
}
/* size1 * (size2 + size3) */
static FLaC__INLINE void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3)
{
if(!size1 || (!size2 && !size3))
return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
size2 += size3;
if(size2 < size3)
return 0;
return safe_malloc_mul_2op_(size1, size2);
}
static FLaC__INLINE void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2)
{
size2 += size1;
if(size2 < size1)
return 0;
return realloc(ptr, size2);
}
static FLaC__INLINE void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3)
{
size2 += size1;
if(size2 < size1)
return 0;
size3 += size2;
if(size3 < size2)
return 0;
return realloc(ptr, size3);
}
static FLaC__INLINE void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4)
{
size2 += size1;
if(size2 < size1)
return 0;
size3 += size2;
if(size3 < size2)
return 0;
size4 += size3;
if(size4 < size3)
return 0;
return realloc(ptr, size4);
}
static FLaC__INLINE void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2)
{
if(!size1 || !size2)
return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
if(size1 > SIZE_MAX / size2)
return 0;
return realloc(ptr, size1*size2);
}
/* size1 * (size2 + size3) */
static FLaC__INLINE void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3)
{
if(!size1 || (!size2 && !size3))
return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
size2 += size3;
if(size2 < size3)
return 0;
return safe_realloc_mul_2op_(ptr, size1, size2);
}
#endif

+ 45
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/assert.h View File

@@ -0,0 +1,45 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FLAC__ASSERT_H
#define FLAC__ASSERT_H
/* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */
#ifdef DEBUG
#include <assert.h>
#define FLAC__ASSERT(x) assert(x)
#define FLAC__ASSERT_DECLARATION(x) x
#else
#define FLAC__ASSERT(x)
#define FLAC__ASSERT_DECLARATION(x)
#endif
#endif

+ 184
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/callback.h View File

@@ -0,0 +1,184 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FLAC__CALLBACK_H
#define FLAC__CALLBACK_H
#include "ordinals.h"
#include <stdlib.h> /* for size_t */
/** \file include/FLAC/callback.h
*
* \brief
* This module defines the structures for describing I/O callbacks
* to the other FLAC interfaces.
*
* See the detailed documentation for callbacks in the
* \link flac_callbacks callbacks \endlink module.
*/
/** \defgroup flac_callbacks FLAC/callback.h: I/O callback structures
* \ingroup flac
*
* \brief
* This module defines the structures for describing I/O callbacks
* to the other FLAC interfaces.
*
* The purpose of the I/O callback functions is to create a common way
* for the metadata interfaces to handle I/O.
*
* Originally the metadata interfaces required filenames as the way of
* specifying FLAC files to operate on. This is problematic in some
* environments so there is an additional option to specify a set of
* callbacks for doing I/O on the FLAC file, instead of the filename.
*
* In addition to the callbacks, a FLAC__IOHandle type is defined as an
* opaque structure for a data source.
*
* The callback function prototypes are similar (but not identical) to the
* stdio functions fread, fwrite, fseek, ftell, feof, and fclose. If you use
* stdio streams to implement the callbacks, you can pass fread, fwrite, and
* fclose anywhere a FLAC__IOCallback_Read, FLAC__IOCallback_Write, or
* FLAC__IOCallback_Close is required, and a FILE* anywhere a FLAC__IOHandle
* is required. \warning You generally CANNOT directly use fseek or ftell
* for FLAC__IOCallback_Seek or FLAC__IOCallback_Tell since on most systems
* these use 32-bit offsets and FLAC requires 64-bit offsets to deal with
* large files. You will have to find an equivalent function (e.g. ftello),
* or write a wrapper. The same is true for feof() since this is usually
* implemented as a macro, not as a function whose address can be taken.
*
* \{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** This is the opaque handle type used by the callbacks. Typically
* this is a \c FILE* or address of a file descriptor.
*/
typedef void* FLAC__IOHandle;
/** Signature for the read callback.
* The signature and semantics match POSIX fread() implementations
* and can generally be used interchangeably.
*
* \param ptr The address of the read buffer.
* \param size The size of the records to be read.
* \param nmemb The number of records to be read.
* \param handle The handle to the data source.
* \retval size_t
* The number of records read.
*/
typedef size_t (*FLAC__IOCallback_Read) (void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle);
/** Signature for the write callback.
* The signature and semantics match POSIX fwrite() implementations
* and can generally be used interchangeably.
*
* \param ptr The address of the write buffer.
* \param size The size of the records to be written.
* \param nmemb The number of records to be written.
* \param handle The handle to the data source.
* \retval size_t
* The number of records written.
*/
typedef size_t (*FLAC__IOCallback_Write) (const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle);
/** Signature for the seek callback.
* The signature and semantics mostly match POSIX fseek() WITH ONE IMPORTANT
* EXCEPTION: the offset is a 64-bit type whereas fseek() is generally 'long'
* and 32-bits wide.
*
* \param handle The handle to the data source.
* \param offset The new position, relative to \a whence
* \param whence \c SEEK_SET, \c SEEK_CUR, or \c SEEK_END
* \retval int
* \c 0 on success, \c -1 on error.
*/
typedef int (*FLAC__IOCallback_Seek) (FLAC__IOHandle handle, FLAC__int64 offset, int whence);
/** Signature for the tell callback.
* The signature and semantics mostly match POSIX ftell() WITH ONE IMPORTANT
* EXCEPTION: the offset is a 64-bit type whereas ftell() is generally 'long'
* and 32-bits wide.
*
* \param handle The handle to the data source.
* \retval FLAC__int64
* The current position on success, \c -1 on error.
*/
typedef FLAC__int64 (*FLAC__IOCallback_Tell) (FLAC__IOHandle handle);
/** Signature for the EOF callback.
* The signature and semantics mostly match POSIX feof() but WATCHOUT:
* on many systems, feof() is a macro, so in this case a wrapper function
* must be provided instead.
*
* \param handle The handle to the data source.
* \retval int
* \c 0 if not at end of file, nonzero if at end of file.
*/
typedef int (*FLAC__IOCallback_Eof) (FLAC__IOHandle handle);
/** Signature for the close callback.
* The signature and semantics match POSIX fclose() implementations
* and can generally be used interchangeably.
*
* \param handle The handle to the data source.
* \retval int
* \c 0 on success, \c EOF on error.
*/
typedef int (*FLAC__IOCallback_Close) (FLAC__IOHandle handle);
/** A structure for holding a set of callbacks.
* Each FLAC interface that requires a FLAC__IOCallbacks structure will
* describe which of the callbacks are required. The ones that are not
* required may be set to NULL.
*
* If the seek requirement for an interface is optional, you can signify that
* a data sorce is not seekable by setting the \a seek field to \c NULL.
*/
typedef struct {
FLAC__IOCallback_Read read;
FLAC__IOCallback_Write write;
FLAC__IOCallback_Seek seek;
FLAC__IOCallback_Tell tell;
FLAC__IOCallback_Eof eof;
FLAC__IOCallback_Close close;
} FLAC__IOCallbacks;
/* \} */
#ifdef __cplusplus
}
#endif
#endif

+ 91
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/export.h View File

@@ -0,0 +1,91 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FLAC__EXPORT_H
#define FLAC__EXPORT_H
/** \file include/FLAC/export.h
*
* \brief
* This module contains #defines and symbols for exporting function
* calls, and providing version information and compiled-in features.
*
* See the \link flac_export export \endlink module.
*/
/** \defgroup flac_export FLAC/export.h: export symbols
* \ingroup flac
*
* \brief
* This module contains #defines and symbols for exporting function
* calls, and providing version information and compiled-in features.
*
* If you are compiling with MSVC and will link to the static library
* (libFLAC.lib) you should define FLAC__NO_DLL in your project to
* make sure the symbols are exported properly.
*
* \{
*/
#if defined(FLAC__NO_DLL) || !defined(_MSC_VER)
#define FLAC_API
#else
#ifdef FLAC_API_EXPORTS
#define FLAC_API _declspec(dllexport)
#else
#define FLAC_API _declspec(dllimport)
#endif
#endif
/** These #defines will mirror the libtool-based library version number, see
* http://www.gnu.org/software/libtool/manual.html#Libtool-versioning
*/
#define FLAC_API_VERSION_CURRENT 10
#define FLAC_API_VERSION_REVISION 0 /**< see above */
#define FLAC_API_VERSION_AGE 2 /**< see above */
#ifdef __cplusplus
extern "C" {
#endif
/** \c 1 if the library has been compiled with support for Ogg FLAC, else \c 0. */
extern FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC;
#ifdef __cplusplus
}
#endif
/* \} */
#endif

+ 1010
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/format.h
File diff suppressed because it is too large
View File


+ 149
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitmath.c View File

@@ -0,0 +1,149 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "include/private/bitmath.h"
#include "../assert.h"
/* An example of what FLAC__bitmath_ilog2() computes:
*
* ilog2( 0) = assertion failure
* ilog2( 1) = 0
* ilog2( 2) = 1
* ilog2( 3) = 1
* ilog2( 4) = 2
* ilog2( 5) = 2
* ilog2( 6) = 2
* ilog2( 7) = 2
* ilog2( 8) = 3
* ilog2( 9) = 3
* ilog2(10) = 3
* ilog2(11) = 3
* ilog2(12) = 3
* ilog2(13) = 3
* ilog2(14) = 3
* ilog2(15) = 3
* ilog2(16) = 4
* ilog2(17) = 4
* ilog2(18) = 4
*/
unsigned FLAC__bitmath_ilog2(FLAC__uint32 v)
{
unsigned l = 0;
FLAC__ASSERT(v > 0);
while(v >>= 1)
l++;
return l;
}
unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v)
{
unsigned l = 0;
FLAC__ASSERT(v > 0);
while(v >>= 1)
l++;
return l;
}
/* An example of what FLAC__bitmath_silog2() computes:
*
* silog2(-10) = 5
* silog2(- 9) = 5
* silog2(- 8) = 4
* silog2(- 7) = 4
* silog2(- 6) = 4
* silog2(- 5) = 4
* silog2(- 4) = 3
* silog2(- 3) = 3
* silog2(- 2) = 2
* silog2(- 1) = 2
* silog2( 0) = 0
* silog2( 1) = 2
* silog2( 2) = 3
* silog2( 3) = 3
* silog2( 4) = 4
* silog2( 5) = 4
* silog2( 6) = 4
* silog2( 7) = 4
* silog2( 8) = 5
* silog2( 9) = 5
* silog2( 10) = 5
*/
unsigned FLAC__bitmath_silog2(int v)
{
while(1) {
if(v == 0) {
return 0;
}
else if(v > 0) {
unsigned l = 0;
while(v) {
l++;
v >>= 1;
}
return l+1;
}
else if(v == -1) {
return 2;
}
else {
v++;
v = -v;
}
}
}
unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v)
{
while(1) {
if(v == 0) {
return 0;
}
else if(v > 0) {
unsigned l = 0;
while(v) {
l++;
v >>= 1;
}
return l+1;
}
else if(v == -1) {
return 2;
}
else {
v++;
v = -v;
}
}
}

+ 1350
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitreader.c
File diff suppressed because it is too large
View File


+ 880
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitwriter.c View File

@@ -0,0 +1,880 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for memcpy(), memset() */
#ifdef _MSC_VER
#include <winsock.h> /* for ntohl() */
#elif defined FLAC__SYS_DARWIN
#include <machine/endian.h> /* for ntohl() */
#elif defined __MINGW32__
#include <winsock.h> /* for ntohl() */
#else
#include <netinet/in.h> /* for ntohl() */
#endif
#if 0 /* UNUSED */
#include "include/private/bitmath.h"
#endif
#include "include/private/bitwriter.h"
#include "include/private/crc.h"
#include "../assert.h"
#include "../alloc.h"
/* Things should be fastest when this matches the machine word size */
/* WATCHOUT: if you change this you must also change the following #defines down to SWAP_BE_WORD_TO_HOST below to match */
/* WATCHOUT: there are a few places where the code will not work unless bwword is >= 32 bits wide */
typedef FLAC__uint32 bwword;
#define FLAC__BYTES_PER_WORD 4
#define FLAC__BITS_PER_WORD 32
#define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff)
/* SWAP_BE_WORD_TO_HOST swaps bytes in a bwword (which is always big-endian) if necessary to match host byte order */
#if WORDS_BIGENDIAN
#define SWAP_BE_WORD_TO_HOST(x) (x)
#else
#ifdef _MSC_VER
#define SWAP_BE_WORD_TO_HOST(x) local_swap32_(x)
#else
#define SWAP_BE_WORD_TO_HOST(x) ntohl(x)
#endif
#endif
/*
* The default capacity here doesn't matter too much. The buffer always grows
* to hold whatever is written to it. Usually the encoder will stop adding at
* a frame or metadata block, then write that out and clear the buffer for the
* next one.
*/
static const unsigned FLAC__BITWRITER_DEFAULT_CAPACITY = 32768u / sizeof(bwword); /* size in words */
/* When growing, increment 4K at a time */
static const unsigned FLAC__BITWRITER_DEFAULT_INCREMENT = 4096u / sizeof(bwword); /* size in words */
#define FLAC__WORDS_TO_BITS(words) ((words) * FLAC__BITS_PER_WORD)
#define FLAC__TOTAL_BITS(bw) (FLAC__WORDS_TO_BITS((bw)->words) + (bw)->bits)
#ifdef min
#undef min
#endif
#define min(x,y) ((x)<(y)?(x):(y))
/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
#ifdef _MSC_VER
#define FLAC__U64L(x) x
#else
#define FLAC__U64L(x) x##LLU
#endif
#ifndef FLaC__INLINE
#define FLaC__INLINE
#endif
struct FLAC__BitWriter {
bwword *buffer;
bwword accum; /* accumulator; bits are right-justified; when full, accum is appended to buffer */
unsigned capacity; /* capacity of buffer in words */
unsigned words; /* # of complete words in buffer */
unsigned bits; /* # of used bits in accum */
};
/* * WATCHOUT: The current implementation only grows the buffer. */
static FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, unsigned bits_to_add)
{
unsigned new_capacity;
bwword *new_buffer;
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
/* calculate total words needed to store 'bits_to_add' additional bits */
new_capacity = bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD);
/* it's possible (due to pessimism in the growth estimation that
* leads to this call) that we don't actually need to grow
*/
if(bw->capacity >= new_capacity)
return true;
/* round up capacity increase to the nearest FLAC__BITWRITER_DEFAULT_INCREMENT */
if((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT)
new_capacity += FLAC__BITWRITER_DEFAULT_INCREMENT - ((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT);
/* make sure we got everything right */
FLAC__ASSERT(0 == (new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT);
FLAC__ASSERT(new_capacity > bw->capacity);
FLAC__ASSERT(new_capacity >= bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD));
new_buffer = (bwword*)safe_realloc_mul_2op_(bw->buffer, sizeof(bwword), /*times*/new_capacity);
if(new_buffer == 0)
return false;
bw->buffer = new_buffer;
bw->capacity = new_capacity;
return true;
}
/***********************************************************************
*
* Class constructor/destructor
*
***********************************************************************/
FLAC__BitWriter *FLAC__bitwriter_new(void)
{
FLAC__BitWriter *bw = (FLAC__BitWriter*)calloc(1, sizeof(FLAC__BitWriter));
/* note that calloc() sets all members to 0 for us */
return bw;
}
void FLAC__bitwriter_delete(FLAC__BitWriter *bw)
{
FLAC__ASSERT(0 != bw);
FLAC__bitwriter_free(bw);
free(bw);
}
/***********************************************************************
*
* Public class methods
*
***********************************************************************/
FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw)
{
FLAC__ASSERT(0 != bw);
bw->words = bw->bits = 0;
bw->capacity = FLAC__BITWRITER_DEFAULT_CAPACITY;
bw->buffer = (bwword*)malloc(sizeof(bwword) * bw->capacity);
if(bw->buffer == 0)
return false;
return true;
}
void FLAC__bitwriter_free(FLAC__BitWriter *bw)
{
FLAC__ASSERT(0 != bw);
if(0 != bw->buffer)
free(bw->buffer);
bw->buffer = 0;
bw->capacity = 0;
bw->words = bw->bits = 0;
}
void FLAC__bitwriter_clear(FLAC__BitWriter *bw)
{
bw->words = bw->bits = 0;
}
void FLAC__bitwriter_dump(const FLAC__BitWriter *bw, FILE *out)
{
unsigned i, j;
if(bw == 0) {
fprintf(out, "bitwriter is NULL\n");
}
else {
fprintf(out, "bitwriter: capacity=%u words=%u bits=%u total_bits=%u\n", bw->capacity, bw->words, bw->bits, FLAC__TOTAL_BITS(bw));
for(i = 0; i < bw->words; i++) {
fprintf(out, "%08X: ", i);
for(j = 0; j < FLAC__BITS_PER_WORD; j++)
fprintf(out, "%01u", bw->buffer[i] & (1 << (FLAC__BITS_PER_WORD-j-1)) ? 1:0);
fprintf(out, "\n");
}
if(bw->bits > 0) {
fprintf(out, "%08X: ", i);
for(j = 0; j < bw->bits; j++)
fprintf(out, "%01u", bw->accum & (1 << (bw->bits-j-1)) ? 1:0);
fprintf(out, "\n");
}
}
}
FLAC__bool FLAC__bitwriter_get_write_crc16(FLAC__BitWriter *bw, FLAC__uint16 *crc)
{
const FLAC__byte *buffer;
size_t bytes;
FLAC__ASSERT((bw->bits & 7) == 0); /* assert that we're byte-aligned */
if(!FLAC__bitwriter_get_buffer(bw, &buffer, &bytes))
return false;
*crc = (FLAC__uint16)FLAC__crc16(buffer, bytes);
FLAC__bitwriter_release_buffer(bw);
return true;
}
FLAC__bool FLAC__bitwriter_get_write_crc8(FLAC__BitWriter *bw, FLAC__byte *crc)
{
const FLAC__byte *buffer;
size_t bytes;
FLAC__ASSERT((bw->bits & 7) == 0); /* assert that we're byte-aligned */
if(!FLAC__bitwriter_get_buffer(bw, &buffer, &bytes))
return false;
*crc = FLAC__crc8(buffer, bytes);
FLAC__bitwriter_release_buffer(bw);
return true;
}
FLAC__bool FLAC__bitwriter_is_byte_aligned(const FLAC__BitWriter *bw)
{
return ((bw->bits & 7) == 0);
}
unsigned FLAC__bitwriter_get_input_bits_unconsumed(const FLAC__BitWriter *bw)
{
return FLAC__TOTAL_BITS(bw);
}
FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **buffer, size_t *bytes)
{
FLAC__ASSERT((bw->bits & 7) == 0);
/* double protection */
if(bw->bits & 7)
return false;
/* if we have bits in the accumulator we have to flush those to the buffer first */
if(bw->bits) {
FLAC__ASSERT(bw->words <= bw->capacity);
if(bw->words == bw->capacity && !bitwriter_grow_(bw, FLAC__BITS_PER_WORD))
return false;
/* append bits as complete word to buffer, but don't change bw->accum or bw->bits */
bw->buffer[bw->words] = SWAP_BE_WORD_TO_HOST(bw->accum << (FLAC__BITS_PER_WORD-bw->bits));
}
/* now we can just return what we have */
*buffer = (FLAC__byte*)bw->buffer;
*bytes = (FLAC__BYTES_PER_WORD * bw->words) + (bw->bits >> 3);
return true;
}
void FLAC__bitwriter_release_buffer(FLAC__BitWriter *bw)
{
/* nothing to do. in the future, strict checking of a 'writer-is-in-
* get-mode' flag could be added everywhere and then cleared here
*/
(void)bw;
}
FLaC__INLINE FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, unsigned bits)
{
unsigned n;
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
if(bits == 0)
return true;
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits))
return false;
/* first part gets to word alignment */
if(bw->bits) {
n = min(FLAC__BITS_PER_WORD - bw->bits, bits);
bw->accum <<= n;
bits -= n;
bw->bits += n;
if(bw->bits == FLAC__BITS_PER_WORD) {
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
bw->bits = 0;
}
else
return true;
}
/* do whole words */
while(bits >= FLAC__BITS_PER_WORD) {
bw->buffer[bw->words++] = 0;
bits -= FLAC__BITS_PER_WORD;
}
/* do any leftovers */
if(bits > 0) {
bw->accum = 0;
bw->bits = bits;
}
return true;
}
FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, unsigned bits)
{
register unsigned left;
/* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */
FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32);
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
FLAC__ASSERT(bits <= 32);
if(bits == 0)
return true;
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits))
return false;
left = FLAC__BITS_PER_WORD - bw->bits;
if(bits < left) {
bw->accum <<= bits;
bw->accum |= val;
bw->bits += bits;
}
else if(bw->bits) { /* WATCHOUT: if bw->bits == 0, left==FLAC__BITS_PER_WORD and bw->accum<<=left is a NOP instead of setting to 0 */
bw->accum <<= left;
bw->accum |= val >> (bw->bits = bits - left);
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
bw->accum = val;
}
else {
bw->accum = val;
bw->bits = 0;
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(val);
}
return true;
}
FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits)
{
/* zero-out unused bits */
if(bits < 32)
val &= (~(0xffffffff << bits));
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits);
}
FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned bits)
{
/* this could be a little faster but it's not used for much */
if(bits > 32) {
return
FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(val>>32), bits-32) &&
FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, 32);
}
else
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits);
}
FLaC__INLINE FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val)
{
/* this doesn't need to be that fast as currently it is only used for vorbis comments */
if(!FLAC__bitwriter_write_raw_uint32(bw, val & 0xff, 8))
return false;
if(!FLAC__bitwriter_write_raw_uint32(bw, (val>>8) & 0xff, 8))
return false;
if(!FLAC__bitwriter_write_raw_uint32(bw, (val>>16) & 0xff, 8))
return false;
if(!FLAC__bitwriter_write_raw_uint32(bw, val>>24, 8))
return false;
return true;
}
FLaC__INLINE FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], unsigned nvals)
{
unsigned i;
/* this could be faster but currently we don't need it to be since it's only used for writing metadata */
for(i = 0; i < nvals; i++) {
if(!FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(vals[i]), 8))
return false;
}
return true;
}
FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, unsigned val)
{
if(val < 32)
return FLAC__bitwriter_write_raw_uint32(bw, 1, ++val);
else
return
FLAC__bitwriter_write_zeroes(bw, val) &&
FLAC__bitwriter_write_raw_uint32(bw, 1, 1);
}
unsigned FLAC__bitwriter_rice_bits(FLAC__int32 val, unsigned parameter)
{
FLAC__uint32 uval;
FLAC__ASSERT(parameter < sizeof(unsigned)*8);
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
uval = (val<<1) ^ (val>>31);
return 1 + parameter + (uval >> parameter);
}
#if 0 /* UNUSED */
unsigned FLAC__bitwriter_golomb_bits_signed(int val, unsigned parameter)
{
unsigned bits, msbs, uval;
unsigned k;
FLAC__ASSERT(parameter > 0);
/* fold signed to unsigned */
if(val < 0)
uval = (unsigned)(((-(++val)) << 1) + 1);
else
uval = (unsigned)(val << 1);
k = FLAC__bitmath_ilog2(parameter);
if(parameter == 1u<<k) {
FLAC__ASSERT(k <= 30);
msbs = uval >> k;
bits = 1 + k + msbs;
}
else {
unsigned q, r, d;
d = (1 << (k+1)) - parameter;
q = uval / parameter;
r = uval - (q * parameter);
bits = 1 + q + k;
if(r >= d)
bits++;
}
return bits;
}
unsigned FLAC__bitwriter_golomb_bits_unsigned(unsigned uval, unsigned parameter)
{
unsigned bits, msbs;
unsigned k;
FLAC__ASSERT(parameter > 0);
k = FLAC__bitmath_ilog2(parameter);
if(parameter == 1u<<k) {
FLAC__ASSERT(k <= 30);
msbs = uval >> k;
bits = 1 + k + msbs;
}
else {
unsigned q, r, d;
d = (1 << (k+1)) - parameter;
q = uval / parameter;
r = uval - (q * parameter);
bits = 1 + q + k;
if(r >= d)
bits++;
}
return bits;
}
#endif /* UNUSED */
FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 val, unsigned parameter)
{
unsigned total_bits, interesting_bits, msbs;
FLAC__uint32 uval, pattern;
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
FLAC__ASSERT(parameter < 8*sizeof(uval));
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
uval = (val<<1) ^ (val>>31);
msbs = uval >> parameter;
interesting_bits = 1 + parameter;
total_bits = interesting_bits + msbs;
pattern = 1 << parameter; /* the unary end bit */
pattern |= (uval & ((1<<parameter)-1)); /* the binary LSBs */
if(total_bits <= 32)
return FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits);
else
return
FLAC__bitwriter_write_zeroes(bw, msbs) && /* write the unary MSBs */
FLAC__bitwriter_write_raw_uint32(bw, pattern, interesting_bits); /* write the unary end bit and binary LSBs */
}
FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FLAC__int32 *vals, unsigned nvals, unsigned parameter)
{
const FLAC__uint32 mask1 = FLAC__WORD_ALL_ONES << parameter; /* we val|=mask1 to set the stop bit above it... */
const FLAC__uint32 mask2 = FLAC__WORD_ALL_ONES >> (31-parameter); /* ...then mask off the bits above the stop bit with val&=mask2*/
FLAC__uint32 uval;
unsigned left;
const unsigned lsbits = 1 + parameter;
unsigned msbits;
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
FLAC__ASSERT(parameter < 8*sizeof(bwword)-1);
/* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */
FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32);
while(nvals) {
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
uval = (*vals<<1) ^ (*vals>>31);
msbits = uval >> parameter;
#if 0 /* OPT: can remove this special case if it doesn't make up for the extra compare (doesn't make a statistically significant difference with msvc or gcc/x86) */
if(bw->bits && bw->bits + msbits + lsbits <= FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current bwword */
/* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free bwword to work in */
bw->bits = bw->bits + msbits + lsbits;
uval |= mask1; /* set stop bit */
uval &= mask2; /* mask off unused top bits */
/* NOT: bw->accum <<= msbits + lsbits because msbits+lsbits could be 32, then the shift would be a NOP */
bw->accum <<= msbits;
bw->accum <<= lsbits;
bw->accum |= uval;
if(bw->bits == FLAC__BITS_PER_WORD) {
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
bw->bits = 0;
/* burying the capacity check down here means we have to grow the buffer a little if there are more vals to do */
if(bw->capacity <= bw->words && nvals > 1 && !bitwriter_grow_(bw, 1)) {
FLAC__ASSERT(bw->capacity == bw->words);
return false;
}
}
}
else {
#elif 1 /*@@@@@@ OPT: try this version with MSVC6 to see if better, not much difference for gcc-4 */
if(bw->bits && bw->bits + msbits + lsbits < FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current bwword */
/* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free bwword to work in */
bw->bits = bw->bits + msbits + lsbits;
uval |= mask1; /* set stop bit */
uval &= mask2; /* mask off unused top bits */
bw->accum <<= msbits + lsbits;
bw->accum |= uval;
}
else {
#endif
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+msbits+lsbits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
/* OPT: pessimism may cause flurry of false calls to grow_ which eat up all savings before it */
if(bw->capacity <= bw->words + bw->bits + msbits + 1/*lsbits always fit in 1 bwword*/ && !bitwriter_grow_(bw, msbits+lsbits))
return false;
if(msbits) {
/* first part gets to word alignment */
if(bw->bits) {
left = FLAC__BITS_PER_WORD - bw->bits;
if(msbits < left) {
bw->accum <<= msbits;
bw->bits += msbits;
goto break1;
}
else {
bw->accum <<= left;
msbits -= left;
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
bw->bits = 0;
}
}
/* do whole words */
while(msbits >= FLAC__BITS_PER_WORD) {
bw->buffer[bw->words++] = 0;
msbits -= FLAC__BITS_PER_WORD;
}
/* do any leftovers */
if(msbits > 0) {
bw->accum = 0;
bw->bits = msbits;
}
}
break1:
uval |= mask1; /* set stop bit */
uval &= mask2; /* mask off unused top bits */
left = FLAC__BITS_PER_WORD - bw->bits;
if(lsbits < left) {
bw->accum <<= lsbits;
bw->accum |= uval;
bw->bits += lsbits;
}
else {
/* if bw->bits == 0, left==FLAC__BITS_PER_WORD which will always
* be > lsbits (because of previous assertions) so it would have
* triggered the (lsbits<left) case above.
*/
FLAC__ASSERT(bw->bits);
FLAC__ASSERT(left < FLAC__BITS_PER_WORD);
bw->accum <<= left;
bw->accum |= uval >> (bw->bits = lsbits - left);
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
bw->accum = uval;
}
#if 1
}
#endif
vals++;
nvals--;
}
return true;
}
#if 0 /* UNUSED */
FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, unsigned parameter)
{
unsigned total_bits, msbs, uval;
unsigned k;
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
FLAC__ASSERT(parameter > 0);
/* fold signed to unsigned */
if(val < 0)
uval = (unsigned)(((-(++val)) << 1) + 1);
else
uval = (unsigned)(val << 1);
k = FLAC__bitmath_ilog2(parameter);
if(parameter == 1u<<k) {
unsigned pattern;
FLAC__ASSERT(k <= 30);
msbs = uval >> k;
total_bits = 1 + k + msbs;
pattern = 1 << k; /* the unary end bit */
pattern |= (uval & ((1u<<k)-1)); /* the binary LSBs */
if(total_bits <= 32) {
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits))
return false;
}
else {
/* write the unary MSBs */
if(!FLAC__bitwriter_write_zeroes(bw, msbs))
return false;
/* write the unary end bit and binary LSBs */
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, k+1))
return false;
}
}
else {
unsigned q, r, d;
d = (1 << (k+1)) - parameter;
q = uval / parameter;
r = uval - (q * parameter);
/* write the unary MSBs */
if(!FLAC__bitwriter_write_zeroes(bw, q))
return false;
/* write the unary end bit */
if(!FLAC__bitwriter_write_raw_uint32(bw, 1, 1))
return false;
/* write the binary LSBs */
if(r >= d) {
if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1))
return false;
}
else {
if(!FLAC__bitwriter_write_raw_uint32(bw, r, k))
return false;
}
}
return true;
}
FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, unsigned uval, unsigned parameter)
{
unsigned total_bits, msbs;
unsigned k;
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
FLAC__ASSERT(parameter > 0);
k = FLAC__bitmath_ilog2(parameter);
if(parameter == 1u<<k) {
unsigned pattern;
FLAC__ASSERT(k <= 30);
msbs = uval >> k;
total_bits = 1 + k + msbs;
pattern = 1 << k; /* the unary end bit */
pattern |= (uval & ((1u<<k)-1)); /* the binary LSBs */
if(total_bits <= 32) {
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits))
return false;
}
else {
/* write the unary MSBs */
if(!FLAC__bitwriter_write_zeroes(bw, msbs))
return false;
/* write the unary end bit and binary LSBs */
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, k+1))
return false;
}
}
else {
unsigned q, r, d;
d = (1 << (k+1)) - parameter;
q = uval / parameter;
r = uval - (q * parameter);
/* write the unary MSBs */
if(!FLAC__bitwriter_write_zeroes(bw, q))
return false;
/* write the unary end bit */
if(!FLAC__bitwriter_write_raw_uint32(bw, 1, 1))
return false;
/* write the binary LSBs */
if(r >= d) {
if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1))
return false;
}
else {
if(!FLAC__bitwriter_write_raw_uint32(bw, r, k))
return false;
}
}
return true;
}
#endif /* UNUSED */
FLAC__bool FLAC__bitwriter_write_utf8_uint32(FLAC__BitWriter *bw, FLAC__uint32 val)
{
FLAC__bool ok = 1;
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
FLAC__ASSERT(!(val & 0x80000000)); /* this version only handles 31 bits */
if(val < 0x80) {
return FLAC__bitwriter_write_raw_uint32(bw, val, 8);
}
else if(val < 0x800) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xC0 | (val>>6), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
}
else if(val < 0x10000) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xE0 | (val>>12), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
}
else if(val < 0x200000) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF0 | (val>>18), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
}
else if(val < 0x4000000) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF8 | (val>>24), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>18)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
}
else {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFC | (val>>30), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>24)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>18)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
}
return ok;
}
FLAC__bool FLAC__bitwriter_write_utf8_uint64(FLAC__BitWriter *bw, FLAC__uint64 val)
{
FLAC__bool ok = 1;
FLAC__ASSERT(0 != bw);
FLAC__ASSERT(0 != bw->buffer);
FLAC__ASSERT(!(val & FLAC__U64L(0xFFFFFFF000000000))); /* this version only handles 36 bits */
if(val < 0x80) {
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, 8);
}
else if(val < 0x800) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xC0 | (FLAC__uint32)(val>>6), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
}
else if(val < 0x10000) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xE0 | (FLAC__uint32)(val>>12), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
}
else if(val < 0x200000) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF0 | (FLAC__uint32)(val>>18), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
}
else if(val < 0x4000000) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF8 | (FLAC__uint32)(val>>24), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
}
else if(val < 0x80000000) {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFC | (FLAC__uint32)(val>>30), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
}
else {
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFE, 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
}
return ok;
}
FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw)
{
/* 0-pad to byte boundary */
if(bw->bits & 7u)
return FLAC__bitwriter_write_zeroes(bw, 8 - (bw->bits & 7u));
else
return true;
}

+ 418
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/cpu.c View File

@@ -0,0 +1,418 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "include/private/cpu.h"
#include <stdlib.h>
#include <stdio.h>
#if defined FLAC__CPU_IA32
# include <signal.h>
#elif defined FLAC__CPU_PPC
# if !defined FLAC__NO_ASM
# if defined FLAC__SYS_DARWIN
# include <sys/sysctl.h>
# include <mach/mach.h>
# include <mach/mach_host.h>
# include <mach/host_info.h>
# include <mach/machine.h>
# ifndef CPU_SUBTYPE_POWERPC_970
# define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100)
# endif
# else /* FLAC__SYS_DARWIN */
# include <signal.h>
# include <setjmp.h>
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump = 0;
static void sigill_handler (int sig)
{
if (!canjump) {
signal (sig, SIG_DFL);
raise (sig);
}
canjump = 0;
siglongjmp (jmpbuf, 1);
}
# endif /* FLAC__SYS_DARWIN */
# endif /* FLAC__NO_ASM */
#endif /* FLAC__CPU_PPC */
#if defined (__NetBSD__) || defined(__OpenBSD__)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
#endif
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
#if defined(__APPLE__)
/* how to get sysctlbyname()? */
#endif
/* these are flags in EDX of CPUID AX=00000001 */
static const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000;
static const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000;
static const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000;
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000;
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000;
/* these are flags in ECX of CPUID AX=00000001 */
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE3 = 0x00000001;
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSSE3 = 0x00000200;
/* these are flags in EDX of CPUID AX=80000001 */
static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000;
static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000;
static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000;
/*
* Extra stuff needed for detection of OS support for SSE on IA-32
*/
#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS
# if defined(__linux__)
/*
* If the OS doesn't support SSE, we will get here with a SIGILL. We
* modify the return address to jump over the offending SSE instruction
* and also the operation following it that indicates the instruction
* executed successfully. In this way we use no global variables and
* stay thread-safe.
*
* 3 + 3 + 6:
* 3 bytes for "xorps xmm0,xmm0"
* 3 bytes for estimate of how long the follwing "inc var" instruction is
* 6 bytes extra in case our estimate is wrong
* 12 bytes puts us in the NOP "landing zone"
*/
# undef USE_OBSOLETE_SIGCONTEXT_FLAVOR /* #define this to use the older signal handler method */
# ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR
static void sigill_handler_sse_os(int signal, struct sigcontext sc)
{
(void)signal;
sc.eip += 3 + 3 + 6;
}
# else
# include <sys/ucontext.h>
static void sigill_handler_sse_os(int signal, siginfo_t *si, void *uc)
{
(void)signal, (void)si;
((ucontext_t*)uc)->uc_mcontext.gregs[14/*REG_EIP*/] += 3 + 3 + 6;
}
# endif
# elif defined(_MSC_VER)
# include <windows.h>
# undef USE_TRY_CATCH_FLAVOR /* #define this to use the try/catch method for catching illegal opcode exception */
# ifdef USE_TRY_CATCH_FLAVOR
# else
LONG CALLBACK sigill_handler_sse_os(EXCEPTION_POINTERS *ep)
{
if(ep->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) {
ep->ContextRecord->Eip += 3 + 3 + 6;
return EXCEPTION_CONTINUE_EXECUTION;
}
return EXCEPTION_CONTINUE_SEARCH;
}
# endif
# endif
#endif
void FLAC__cpu_info(FLAC__CPUInfo *info)
{
/*
* IA32-specific
*/
#ifdef FLAC__CPU_IA32
info->type = FLAC__CPUINFO_TYPE_IA32;
#if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM
info->use_asm = true; /* we assume a minimum of 80386 with FLAC__CPU_IA32 */
info->data.ia32.cpuid = FLAC__cpu_have_cpuid_asm_ia32()? true : false;
info->data.ia32.bswap = info->data.ia32.cpuid; /* CPUID => BSWAP since it came after */
info->data.ia32.cmov = false;
info->data.ia32.mmx = false;
info->data.ia32.fxsr = false;
info->data.ia32.sse = false;
info->data.ia32.sse2 = false;
info->data.ia32.sse3 = false;
info->data.ia32.ssse3 = false;
info->data.ia32._3dnow = false;
info->data.ia32.ext3dnow = false;
info->data.ia32.extmmx = false;
if(info->data.ia32.cpuid) {
/* http://www.sandpile.org/ia32/cpuid.htm */
FLAC__uint32 flags_edx, flags_ecx;
FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx);
info->data.ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false;
info->data.ia32.mmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX )? true : false;
info->data.ia32.fxsr = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false;
info->data.ia32.sse = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE )? true : false;
info->data.ia32.sse2 = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false;
info->data.ia32.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false;
info->data.ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false;
#ifdef FLAC__USE_3DNOW
flags_edx = FLAC__cpu_info_extended_amd_asm_ia32();
info->data.ia32._3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW )? true : false;
info->data.ia32.ext3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW)? true : false;
info->data.ia32.extmmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX )? true : false;
#else
info->data.ia32._3dnow = info->data.ia32.ext3dnow = info->data.ia32.extmmx = false;
#endif
#ifdef DEBUG
fprintf(stderr, "CPU info (IA-32):\n");
fprintf(stderr, " CPUID ...... %c\n", info->data.ia32.cpuid ? 'Y' : 'n');
fprintf(stderr, " BSWAP ...... %c\n", info->data.ia32.bswap ? 'Y' : 'n');
fprintf(stderr, " CMOV ....... %c\n", info->data.ia32.cmov ? 'Y' : 'n');
fprintf(stderr, " MMX ........ %c\n", info->data.ia32.mmx ? 'Y' : 'n');
fprintf(stderr, " FXSR ....... %c\n", info->data.ia32.fxsr ? 'Y' : 'n');
fprintf(stderr, " SSE ........ %c\n", info->data.ia32.sse ? 'Y' : 'n');
fprintf(stderr, " SSE2 ....... %c\n", info->data.ia32.sse2 ? 'Y' : 'n');
fprintf(stderr, " SSE3 ....... %c\n", info->data.ia32.sse3 ? 'Y' : 'n');
fprintf(stderr, " SSSE3 ...... %c\n", info->data.ia32.ssse3 ? 'Y' : 'n');
fprintf(stderr, " 3DNow! ..... %c\n", info->data.ia32._3dnow ? 'Y' : 'n');
fprintf(stderr, " 3DNow!-ext . %c\n", info->data.ia32.ext3dnow? 'Y' : 'n');
fprintf(stderr, " 3DNow!-MMX . %c\n", info->data.ia32.extmmx ? 'Y' : 'n');
#endif
/*
* now have to check for OS support of SSE/SSE2
*/
if(info->data.ia32.fxsr || info->data.ia32.sse || info->data.ia32.sse2) {
#if defined FLAC__NO_SSE_OS
/* assume user knows better than us; turn it off */
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
#elif defined FLAC__SSE_OS
/* assume user knows better than us; leave as detected above */
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__APPLE__)
int sse = 0;
size_t len;
/* at least one of these must work: */
len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse);
len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse" , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */
if(!sse)
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
#elif defined(__NetBSD__) || defined (__OpenBSD__)
# if __NetBSD_Version__ >= 105250000 || (defined __OpenBSD__)
int val = 0, mib[2] = { CTL_MACHDEP, CPU_SSE };
size_t len = sizeof(val);
if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val)
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
else { /* double-check SSE2 */
mib[1] = CPU_SSE2;
len = sizeof(val);
if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val)
info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
}
# else
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
# endif
#elif defined(__linux__)
int sse = 0;
struct sigaction sigill_save;
#ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR
if(0 == sigaction(SIGILL, NULL, &sigill_save) && signal(SIGILL, (void (*)(int))sigill_handler_sse_os) != SIG_ERR)
#else
struct sigaction sigill_sse;
sigill_sse.sa_sigaction = sigill_handler_sse_os;
__sigemptyset(&sigill_sse.sa_mask);
sigill_sse.sa_flags = SA_SIGINFO | SA_RESETHAND; /* SA_RESETHAND just in case our SIGILL return jump breaks, so we don't get stuck in a loop */
if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save))
#endif
{
/* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */
/* see sigill_handler_sse_os() for an explanation of the following: */
asm volatile (
"xorl %0,%0\n\t" /* for some reason, still need to do this to clear 'sse' var */
"xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */
"incl %0\n\t" /* SIGILL handler will jump over this */
/* landing zone */
"nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t" /* SIGILL jump lands here if "inc" is 3 bytes (expected) */
"nop\n\t"
"nop" /* SIGILL jump lands here if "inc" is 1 byte */
: "=r"(sse)
: "r"(sse)
);
sigaction(SIGILL, &sigill_save, NULL);
}
if(!sse)
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
#elif defined(_MSC_VER)
# ifdef USE_TRY_CATCH_FLAVOR
_try {
__asm {
# if _MSC_VER <= 1200
/* VC6 assembler doesn't know SSE, have to emit bytecode instead */
_emit 0x0F
_emit 0x57
_emit 0xC0
# else
xorps xmm0,xmm0
# endif
}
}
_except(EXCEPTION_EXECUTE_HANDLER) {
if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
}
# else
int sse = 0;
LPTOP_LEVEL_EXCEPTION_FILTER save = SetUnhandledExceptionFilter(sigill_handler_sse_os);
/* see GCC version above for explanation */
/* http://msdn2.microsoft.com/en-us/library/4ks26t93.aspx */
/* http://www.codeproject.com/cpp/gccasm.asp */
/* http://www.hick.org/~mmiller/msvc_inline_asm.html */
__asm {
# if _MSC_VER <= 1200
/* VC6 assembler doesn't know SSE, have to emit bytecode instead */
_emit 0x0F
_emit 0x57
_emit 0xC0
# else
xorps xmm0,xmm0
# endif
inc sse
nop
nop
nop
nop
nop
nop
nop
nop
nop
}
SetUnhandledExceptionFilter(save);
if(!sse)
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
# endif
#else
/* no way to test, disable to be safe */
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
#endif
#ifdef DEBUG
fprintf(stderr, " SSE OS sup . %c\n", info->data.ia32.sse ? 'Y' : 'n');
#endif
}
}
#else
info->use_asm = false;
#endif
/*
* PPC-specific
*/
#elif defined FLAC__CPU_PPC
info->type = FLAC__CPUINFO_TYPE_PPC;
# if !defined FLAC__NO_ASM
info->use_asm = true;
# ifdef FLAC__USE_ALTIVEC
# if defined FLAC__SYS_DARWIN
{
int val = 0, mib[2] = { CTL_HW, HW_VECTORUNIT };
size_t len = sizeof(val);
info->data.ppc.altivec = !(sysctl(mib, 2, &val, &len, NULL, 0) || !val);
}
{
host_basic_info_data_t hostInfo;
mach_msg_type_number_t infoCount;
infoCount = HOST_BASIC_INFO_COUNT;
host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount);
info->data.ppc.ppc64 = (hostInfo.cpu_type == CPU_TYPE_POWERPC) && (hostInfo.cpu_subtype == CPU_SUBTYPE_POWERPC_970);
}
# else /* FLAC__USE_ALTIVEC && !FLAC__SYS_DARWIN */
{
/* no Darwin, do it the brute-force way */
/* @@@@@@ this is not thread-safe; replace with SSE OS method above or remove */
info->data.ppc.altivec = 0;
info->data.ppc.ppc64 = 0;
signal (SIGILL, sigill_handler);
canjump = 0;
if (!sigsetjmp (jmpbuf, 1)) {
canjump = 1;
asm volatile (
"mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
:
: "r" (-1)
);
info->data.ppc.altivec = 1;
}
canjump = 0;
if (!sigsetjmp (jmpbuf, 1)) {
int x = 0;
canjump = 1;
/* PPC64 hardware implements the cntlzd instruction */
asm volatile ("cntlzd %0, %1" : "=r" (x) : "r" (x) );
info->data.ppc.ppc64 = 1;
}
signal (SIGILL, SIG_DFL); /*@@@@@@ should save and restore old signal */
}
# endif
# else /* !FLAC__USE_ALTIVEC */
info->data.ppc.altivec = 0;
info->data.ppc.ppc64 = 0;
# endif
# else
info->use_asm = false;
# endif
/*
* unknown CPI
*/
#else
info->type = FLAC__CPUINFO_TYPE_UNKNOWN;
info->use_asm = false;
#endif
}

+ 142
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/crc.c View File

@@ -0,0 +1,142 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "include/private/crc.h"
/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
FLAC__byte const FLAC__crc8_table[256] = {
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
};
/* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */
unsigned FLAC__crc16_table[256] = {
0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
};
void FLAC__crc8_update(const FLAC__byte data, FLAC__uint8 *crc)
{
*crc = FLAC__crc8_table[*crc ^ data];
}
void FLAC__crc8_update_block(const FLAC__byte *data, unsigned len, FLAC__uint8 *crc)
{
while(len--)
*crc = FLAC__crc8_table[*crc ^ *data++];
}
FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len)
{
FLAC__uint8 crc = 0;
while(len--)
crc = FLAC__crc8_table[crc ^ *data++];
return crc;
}
unsigned FLAC__crc16(const FLAC__byte *data, unsigned len)
{
unsigned crc = 0;
while(len--)
crc = ((crc<<8) ^ FLAC__crc16_table[(crc>>8) ^ *data++]) & 0xffff;
return crc;
}

+ 435
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/fixed.c View File

@@ -0,0 +1,435 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <math.h>
#include <string.h>
#include "include/private/bitmath.h"
#include "include/private/fixed.h"
#include "../assert.h"
#ifndef M_LN2
/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */
#define M_LN2 0.69314718055994530942
#endif
#ifdef min
#undef min
#endif
#define min(x,y) ((x) < (y)? (x) : (y))
#ifdef local_abs
#undef local_abs
#endif
#define local_abs(x) ((unsigned)((x)<0? -(x) : (x)))
#ifdef FLAC__INTEGER_ONLY_LIBRARY
/* rbps stands for residual bits per sample
*
* (ln(2) * err)
* rbps = log (-----------)
* 2 ( n )
*/
static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__uint32 n)
{
FLAC__uint32 rbps;
unsigned bits; /* the number of bits required to represent a number */
int fracbits; /* the number of bits of rbps that comprise the fractional part */
FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint));
FLAC__ASSERT(err > 0);
FLAC__ASSERT(n > 0);
FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE);
if(err <= n)
return 0;
/*
* The above two things tell us 1) n fits in 16 bits; 2) err/n > 1.
* These allow us later to know we won't lose too much precision in the
* fixed-point division (err<<fracbits)/n.
*/
fracbits = (8*sizeof(err)) - (FLAC__bitmath_ilog2(err)+1);
err <<= fracbits;
err /= n;
/* err now holds err/n with fracbits fractional bits */
/*
* Whittle err down to 16 bits max. 16 significant bits is enough for
* our purposes.
*/
FLAC__ASSERT(err > 0);
bits = FLAC__bitmath_ilog2(err)+1;
if(bits > 16) {
err >>= (bits-16);
fracbits -= (bits-16);
}
rbps = (FLAC__uint32)err;
/* Multiply by fixed-point version of ln(2), with 16 fractional bits */
rbps *= FLAC__FP_LN2;
fracbits += 16;
FLAC__ASSERT(fracbits >= 0);
/* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */
{
const int f = fracbits & 3;
if(f) {
rbps >>= f;
fracbits -= f;
}
}
rbps = FLAC__fixedpoint_log2(rbps, fracbits, (unsigned)(-1));
if(rbps == 0)
return 0;
/*
* The return value must have 16 fractional bits. Since the whole part
* of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits
* must be >= -3, these assertion allows us to be able to shift rbps
* left if necessary to get 16 fracbits without losing any bits of the
* whole part of rbps.
*
* There is a slight chance due to accumulated error that the whole part
* will require 6 bits, so we use 6 in the assertion. Really though as
* long as it fits in 13 bits (32 - (16 - (-3))) we are fine.
*/
FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6);
FLAC__ASSERT(fracbits >= -3);
/* now shift the decimal point into place */
if(fracbits < 16)
return rbps << (16-fracbits);
else if(fracbits > 16)
return rbps >> (fracbits-16);
else
return rbps;
}
static FLAC__fixedpoint local__compute_rbps_wide_integerized(FLAC__uint64 err, FLAC__uint32 n)
{
FLAC__uint32 rbps;
unsigned bits; /* the number of bits required to represent a number */
int fracbits; /* the number of bits of rbps that comprise the fractional part */
FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint));
FLAC__ASSERT(err > 0);
FLAC__ASSERT(n > 0);
FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE);
if(err <= n)
return 0;
/*
* The above two things tell us 1) n fits in 16 bits; 2) err/n > 1.
* These allow us later to know we won't lose too much precision in the
* fixed-point division (err<<fracbits)/n.
*/
fracbits = (8*sizeof(err)) - (FLAC__bitmath_ilog2_wide(err)+1);
err <<= fracbits;
err /= n;
/* err now holds err/n with fracbits fractional bits */
/*
* Whittle err down to 16 bits max. 16 significant bits is enough for
* our purposes.
*/
FLAC__ASSERT(err > 0);
bits = FLAC__bitmath_ilog2_wide(err)+1;
if(bits > 16) {
err >>= (bits-16);
fracbits -= (bits-16);
}
rbps = (FLAC__uint32)err;
/* Multiply by fixed-point version of ln(2), with 16 fractional bits */
rbps *= FLAC__FP_LN2;
fracbits += 16;
FLAC__ASSERT(fracbits >= 0);
/* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */
{
const int f = fracbits & 3;
if(f) {
rbps >>= f;
fracbits -= f;
}
}
rbps = FLAC__fixedpoint_log2(rbps, fracbits, (unsigned)(-1));
if(rbps == 0)
return 0;
/*
* The return value must have 16 fractional bits. Since the whole part
* of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits
* must be >= -3, these assertion allows us to be able to shift rbps
* left if necessary to get 16 fracbits without losing any bits of the
* whole part of rbps.
*
* There is a slight chance due to accumulated error that the whole part
* will require 6 bits, so we use 6 in the assertion. Really though as
* long as it fits in 13 bits (32 - (16 - (-3))) we are fine.
*/
FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6);
FLAC__ASSERT(fracbits >= -3);
/* now shift the decimal point into place */
if(fracbits < 16)
return rbps << (16-fracbits);
else if(fracbits > 16)
return rbps >> (fracbits-16);
else
return rbps;
}
#endif
#ifndef FLAC__INTEGER_ONLY_LIBRARY
unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
#else
unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
#endif
{
FLAC__int32 last_error_0 = data[-1];
FLAC__int32 last_error_1 = data[-1] - data[-2];
FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]);
FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]);
FLAC__int32 error, save;
FLAC__uint32 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
unsigned i, order;
for(i = 0; i < data_len; i++) {
error = data[i] ; total_error_0 += local_abs(error); save = error;
error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error;
error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error;
error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error;
error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save;
}
if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4))
order = 0;
else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4))
order = 1;
else if(total_error_2 < min(total_error_3, total_error_4))
order = 2;
else if(total_error_3 < total_error_4)
order = 3;
else
order = 4;
/* Estimate the expected number of bits per residual signal sample. */
/* 'total_error*' is linearly related to the variance of the residual */
/* signal, so we use it directly to compute E(|x|) */
FLAC__ASSERT(data_len > 0 || total_error_0 == 0);
FLAC__ASSERT(data_len > 0 || total_error_1 == 0);
FLAC__ASSERT(data_len > 0 || total_error_2 == 0);
FLAC__ASSERT(data_len > 0 || total_error_3 == 0);
FLAC__ASSERT(data_len > 0 || total_error_4 == 0);
#ifndef FLAC__INTEGER_ONLY_LIBRARY
residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0);
#else
residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_integerized(total_error_0, data_len) : 0;
residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_integerized(total_error_1, data_len) : 0;
residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_integerized(total_error_2, data_len) : 0;
residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_integerized(total_error_3, data_len) : 0;
residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_integerized(total_error_4, data_len) : 0;
#endif
return order;
}
#ifndef FLAC__INTEGER_ONLY_LIBRARY
unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
#else
unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
#endif
{
FLAC__int32 last_error_0 = data[-1];
FLAC__int32 last_error_1 = data[-1] - data[-2];
FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]);
FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]);
FLAC__int32 error, save;
/* total_error_* are 64-bits to avoid overflow when encoding
* erratic signals when the bits-per-sample and blocksize are
* large.
*/
FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
unsigned i, order;
for(i = 0; i < data_len; i++) {
error = data[i] ; total_error_0 += local_abs(error); save = error;
error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error;
error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error;
error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error;
error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save;
}
if(total_error_0 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4))
order = 0;
else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4))
order = 1;
else if(total_error_2 < min(total_error_3, total_error_4))
order = 2;
else if(total_error_3 < total_error_4)
order = 3;
else
order = 4;
/* Estimate the expected number of bits per residual signal sample. */
/* 'total_error*' is linearly related to the variance of the residual */
/* signal, so we use it directly to compute E(|x|) */
FLAC__ASSERT(data_len > 0 || total_error_0 == 0);
FLAC__ASSERT(data_len > 0 || total_error_1 == 0);
FLAC__ASSERT(data_len > 0 || total_error_2 == 0);
FLAC__ASSERT(data_len > 0 || total_error_3 == 0);
FLAC__ASSERT(data_len > 0 || total_error_4 == 0);
#ifndef FLAC__INTEGER_ONLY_LIBRARY
#if defined _MSC_VER || defined __MINGW32__
/* with MSVC you have to spoon feed it the casting */
residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0);
#else
residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0);
#endif
#else
residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_wide_integerized(total_error_0, data_len) : 0;
residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_wide_integerized(total_error_1, data_len) : 0;
residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_wide_integerized(total_error_2, data_len) : 0;
residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_wide_integerized(total_error_3, data_len) : 0;
residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_wide_integerized(total_error_4, data_len) : 0;
#endif
return order;
}
void FLAC__fixed_compute_residual(const FLAC__int32 data[], unsigned data_len, unsigned order, FLAC__int32 residual[])
{
const int idata_len = (int)data_len;
int i;
switch(order) {
case 0:
FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0]));
memcpy(residual, data, sizeof(residual[0])*data_len);
break;
case 1:
for(i = 0; i < idata_len; i++)
residual[i] = data[i] - data[i-1];
break;
case 2:
for(i = 0; i < idata_len; i++)
#if 1 /* OPT: may be faster with some compilers on some systems */
residual[i] = data[i] - (data[i-1] << 1) + data[i-2];
#else
residual[i] = data[i] - 2*data[i-1] + data[i-2];
#endif
break;
case 3:
for(i = 0; i < idata_len; i++)
#if 1 /* OPT: may be faster with some compilers on some systems */
residual[i] = data[i] - (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) - data[i-3];
#else
residual[i] = data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3];
#endif
break;
case 4:
for(i = 0; i < idata_len; i++)
#if 1 /* OPT: may be faster with some compilers on some systems */
residual[i] = data[i] - ((data[i-1]+data[i-3])<<2) + ((data[i-2]<<2) + (data[i-2]<<1)) + data[i-4];
#else
residual[i] = data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4];
#endif
break;
default:
FLAC__ASSERT(0);
}
}
void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, unsigned order, FLAC__int32 data[])
{
int i, idata_len = (int)data_len;
switch(order) {
case 0:
FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0]));
memcpy(data, residual, sizeof(residual[0])*data_len);
break;
case 1:
for(i = 0; i < idata_len; i++)
data[i] = residual[i] + data[i-1];
break;
case 2:
for(i = 0; i < idata_len; i++)
#if 1 /* OPT: may be faster with some compilers on some systems */
data[i] = residual[i] + (data[i-1]<<1) - data[i-2];
#else
data[i] = residual[i] + 2*data[i-1] - data[i-2];
#endif
break;
case 3:
for(i = 0; i < idata_len; i++)
#if 1 /* OPT: may be faster with some compilers on some systems */
data[i] = residual[i] + (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) + data[i-3];
#else
data[i] = residual[i] + 3*data[i-1] - 3*data[i-2] + data[i-3];
#endif
break;
case 4:
for(i = 0; i < idata_len; i++)
#if 1 /* OPT: may be faster with some compilers on some systems */
data[i] = residual[i] + ((data[i-1]+data[i-3])<<2) - ((data[i-2]<<2) + (data[i-2]<<1)) - data[i-4];
#else
data[i] = residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4];
#endif
break;
default:
FLAC__ASSERT(0);
}
}

+ 308
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/float.c View File

@@ -0,0 +1,308 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include "../assert.h"
#include "include/private/float.h"
#ifdef FLAC__INTEGER_ONLY_LIBRARY
/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
#ifdef _MSC_VER
#define FLAC__U64L(x) x
#else
#define FLAC__U64L(x) x##LLU
#endif
const FLAC__fixedpoint FLAC__FP_ZERO = 0;
const FLAC__fixedpoint FLAC__FP_ONE_HALF = 0x00008000;
const FLAC__fixedpoint FLAC__FP_ONE = 0x00010000;
const FLAC__fixedpoint FLAC__FP_LN2 = 45426;
const FLAC__fixedpoint FLAC__FP_E = 178145;
/* Lookup tables for Knuth's logarithm algorithm */
#define LOG2_LOOKUP_PRECISION 16
static const FLAC__uint32 log2_lookup[][LOG2_LOOKUP_PRECISION] = {
{
/*
* 0 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ 0x00000001,
/* lg(4/3) = */ 0x00000000,
/* lg(8/7) = */ 0x00000000,
/* lg(16/15) = */ 0x00000000,
/* lg(32/31) = */ 0x00000000,
/* lg(64/63) = */ 0x00000000,
/* lg(128/127) = */ 0x00000000,
/* lg(256/255) = */ 0x00000000,
/* lg(512/511) = */ 0x00000000,
/* lg(1024/1023) = */ 0x00000000,
/* lg(2048/2047) = */ 0x00000000,
/* lg(4096/4095) = */ 0x00000000,
/* lg(8192/8191) = */ 0x00000000,
/* lg(16384/16383) = */ 0x00000000,
/* lg(32768/32767) = */ 0x00000000
},
{
/*
* 4 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ 0x00000010,
/* lg(4/3) = */ 0x00000007,
/* lg(8/7) = */ 0x00000003,
/* lg(16/15) = */ 0x00000001,
/* lg(32/31) = */ 0x00000001,
/* lg(64/63) = */ 0x00000000,
/* lg(128/127) = */ 0x00000000,
/* lg(256/255) = */ 0x00000000,
/* lg(512/511) = */ 0x00000000,
/* lg(1024/1023) = */ 0x00000000,
/* lg(2048/2047) = */ 0x00000000,
/* lg(4096/4095) = */ 0x00000000,
/* lg(8192/8191) = */ 0x00000000,
/* lg(16384/16383) = */ 0x00000000,
/* lg(32768/32767) = */ 0x00000000
},
{
/*
* 8 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ 0x00000100,
/* lg(4/3) = */ 0x0000006a,
/* lg(8/7) = */ 0x00000031,
/* lg(16/15) = */ 0x00000018,
/* lg(32/31) = */ 0x0000000c,
/* lg(64/63) = */ 0x00000006,
/* lg(128/127) = */ 0x00000003,
/* lg(256/255) = */ 0x00000001,
/* lg(512/511) = */ 0x00000001,
/* lg(1024/1023) = */ 0x00000000,
/* lg(2048/2047) = */ 0x00000000,
/* lg(4096/4095) = */ 0x00000000,
/* lg(8192/8191) = */ 0x00000000,
/* lg(16384/16383) = */ 0x00000000,
/* lg(32768/32767) = */ 0x00000000
},
{
/*
* 12 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ 0x00001000,
/* lg(4/3) = */ 0x000006a4,
/* lg(8/7) = */ 0x00000315,
/* lg(16/15) = */ 0x0000017d,
/* lg(32/31) = */ 0x000000bc,
/* lg(64/63) = */ 0x0000005d,
/* lg(128/127) = */ 0x0000002e,
/* lg(256/255) = */ 0x00000017,
/* lg(512/511) = */ 0x0000000c,
/* lg(1024/1023) = */ 0x00000006,
/* lg(2048/2047) = */ 0x00000003,
/* lg(4096/4095) = */ 0x00000001,
/* lg(8192/8191) = */ 0x00000001,
/* lg(16384/16383) = */ 0x00000000,
/* lg(32768/32767) = */ 0x00000000
},
{
/*
* 16 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ 0x00010000,
/* lg(4/3) = */ 0x00006a40,
/* lg(8/7) = */ 0x00003151,
/* lg(16/15) = */ 0x000017d6,
/* lg(32/31) = */ 0x00000bba,
/* lg(64/63) = */ 0x000005d1,
/* lg(128/127) = */ 0x000002e6,
/* lg(256/255) = */ 0x00000172,
/* lg(512/511) = */ 0x000000b9,
/* lg(1024/1023) = */ 0x0000005c,
/* lg(2048/2047) = */ 0x0000002e,
/* lg(4096/4095) = */ 0x00000017,
/* lg(8192/8191) = */ 0x0000000c,
/* lg(16384/16383) = */ 0x00000006,
/* lg(32768/32767) = */ 0x00000003
},
{
/*
* 20 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ 0x00100000,
/* lg(4/3) = */ 0x0006a3fe,
/* lg(8/7) = */ 0x00031513,
/* lg(16/15) = */ 0x00017d60,
/* lg(32/31) = */ 0x0000bb9d,
/* lg(64/63) = */ 0x00005d10,
/* lg(128/127) = */ 0x00002e59,
/* lg(256/255) = */ 0x00001721,
/* lg(512/511) = */ 0x00000b8e,
/* lg(1024/1023) = */ 0x000005c6,
/* lg(2048/2047) = */ 0x000002e3,
/* lg(4096/4095) = */ 0x00000171,
/* lg(8192/8191) = */ 0x000000b9,
/* lg(16384/16383) = */ 0x0000005c,
/* lg(32768/32767) = */ 0x0000002e
},
{
/*
* 24 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ 0x01000000,
/* lg(4/3) = */ 0x006a3fe6,
/* lg(8/7) = */ 0x00315130,
/* lg(16/15) = */ 0x0017d605,
/* lg(32/31) = */ 0x000bb9ca,
/* lg(64/63) = */ 0x0005d0fc,
/* lg(128/127) = */ 0x0002e58f,
/* lg(256/255) = */ 0x0001720e,
/* lg(512/511) = */ 0x0000b8d8,
/* lg(1024/1023) = */ 0x00005c61,
/* lg(2048/2047) = */ 0x00002e2d,
/* lg(4096/4095) = */ 0x00001716,
/* lg(8192/8191) = */ 0x00000b8b,
/* lg(16384/16383) = */ 0x000005c5,
/* lg(32768/32767) = */ 0x000002e3
},
{
/*
* 28 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ 0x10000000,
/* lg(4/3) = */ 0x06a3fe5c,
/* lg(8/7) = */ 0x03151301,
/* lg(16/15) = */ 0x017d6049,
/* lg(32/31) = */ 0x00bb9ca6,
/* lg(64/63) = */ 0x005d0fba,
/* lg(128/127) = */ 0x002e58f7,
/* lg(256/255) = */ 0x001720da,
/* lg(512/511) = */ 0x000b8d87,
/* lg(1024/1023) = */ 0x0005c60b,
/* lg(2048/2047) = */ 0x0002e2d7,
/* lg(4096/4095) = */ 0x00017160,
/* lg(8192/8191) = */ 0x0000b8ad,
/* lg(16384/16383) = */ 0x00005c56,
/* lg(32768/32767) = */ 0x00002e2b
}
};
#if 0
static const FLAC__uint64 log2_lookup_wide[] = {
{
/*
* 32 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ FLAC__U64L(0x100000000),
/* lg(4/3) = */ FLAC__U64L(0x6a3fe5c6),
/* lg(8/7) = */ FLAC__U64L(0x31513015),
/* lg(16/15) = */ FLAC__U64L(0x17d60497),
/* lg(32/31) = */ FLAC__U64L(0x0bb9ca65),
/* lg(64/63) = */ FLAC__U64L(0x05d0fba2),
/* lg(128/127) = */ FLAC__U64L(0x02e58f74),
/* lg(256/255) = */ FLAC__U64L(0x01720d9c),
/* lg(512/511) = */ FLAC__U64L(0x00b8d875),
/* lg(1024/1023) = */ FLAC__U64L(0x005c60aa),
/* lg(2048/2047) = */ FLAC__U64L(0x002e2d72),
/* lg(4096/4095) = */ FLAC__U64L(0x00171600),
/* lg(8192/8191) = */ FLAC__U64L(0x000b8ad2),
/* lg(16384/16383) = */ FLAC__U64L(0x0005c55d),
/* lg(32768/32767) = */ FLAC__U64L(0x0002e2ac)
},
{
/*
* 48 fraction bits
*/
/* undefined */ 0x00000000,
/* lg(2/1) = */ FLAC__U64L(0x1000000000000),
/* lg(4/3) = */ FLAC__U64L(0x6a3fe5c60429),
/* lg(8/7) = */ FLAC__U64L(0x315130157f7a),
/* lg(16/15) = */ FLAC__U64L(0x17d60496cfbb),
/* lg(32/31) = */ FLAC__U64L(0xbb9ca64ecac),
/* lg(64/63) = */ FLAC__U64L(0x5d0fba187cd),
/* lg(128/127) = */ FLAC__U64L(0x2e58f7441ee),
/* lg(256/255) = */ FLAC__U64L(0x1720d9c06a8),
/* lg(512/511) = */ FLAC__U64L(0xb8d8752173),
/* lg(1024/1023) = */ FLAC__U64L(0x5c60aa252e),
/* lg(2048/2047) = */ FLAC__U64L(0x2e2d71b0d8),
/* lg(4096/4095) = */ FLAC__U64L(0x1716001719),
/* lg(8192/8191) = */ FLAC__U64L(0xb8ad1de1b),
/* lg(16384/16383) = */ FLAC__U64L(0x5c55d640d),
/* lg(32768/32767) = */ FLAC__U64L(0x2e2abcf52)
}
};
#endif
FLAC__uint32 FLAC__fixedpoint_log2(FLAC__uint32 x, unsigned fracbits, unsigned precision)
{
const FLAC__uint32 ONE = (1u << fracbits);
const FLAC__uint32 *table = log2_lookup[fracbits >> 2];
FLAC__ASSERT(fracbits < 32);
FLAC__ASSERT((fracbits & 0x3) == 0);
if(x < ONE)
return 0;
if(precision > LOG2_LOOKUP_PRECISION)
precision = LOG2_LOOKUP_PRECISION;
/* Knuth's algorithm for computing logarithms, optimized for base-2 with lookup tables */
{
FLAC__uint32 y = 0;
FLAC__uint32 z = x >> 1, k = 1;
while (x > ONE && k < precision) {
if (x - z >= ONE) {
x -= z;
z = x >> k;
y += table[k];
}
else {
z >>= 1;
k++;
}
}
return y;
}
}
#endif /* defined FLAC__INTEGER_ONLY_LIBRARY */

+ 598
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/format.c View File

@@ -0,0 +1,598 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h> /* for qsort() */
#include <string.h> /* for memset() */
#include "../assert.h"
#include "../format.h"
#include "include/private/format.h"
#ifndef FLaC__INLINE
#define FLaC__INLINE
#endif
#ifdef min
#undef min
#endif
#define min(a,b) ((a)<(b)?(a):(b))
/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
#ifdef _MSC_VER
#define FLAC__U64L(x) x
#else
#define FLAC__U64L(x) x##LLU
#endif
/* VERSION should come from configure */
FLAC_API const char *FLAC__VERSION_STRING = VERSION
;
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINW32__
/* yet one more hack because of MSVC6: */
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.2.1 20070917";
#else
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20070917";
#endif
FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143;
FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */
FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff);
FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe;
FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 1; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN = 1; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */
FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */
FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN = 5; /* bits */
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER = 31; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */
FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[] = {
"PARTITIONED_RICE",
"PARTITIONED_RICE2"
};
FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN = 4; /* bits */
FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN = 5; /* bits */
FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN = 1; /* bits */
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN = 6; /* bits */
FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN = 1; /* bits */
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK = 0x00;
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK = 0x02;
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK = 0x10;
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK = 0x40;
FLAC_API const char * const FLAC__SubframeTypeString[] = {
"CONSTANT",
"VERBATIM",
"FIXED",
"LPC"
};
FLAC_API const char * const FLAC__ChannelAssignmentString[] = {
"INDEPENDENT",
"LEFT_SIDE",
"RIGHT_SIDE",
"MID_SIDE"
};
FLAC_API const char * const FLAC__FrameNumberTypeString[] = {
"FRAME_NUMBER_TYPE_FRAME_NUMBER",
"FRAME_NUMBER_TYPE_SAMPLE_NUMBER"
};
FLAC_API const char * const FLAC__MetadataTypeString[] = {
"STREAMINFO",
"PADDING",
"APPLICATION",
"SEEKTABLE",
"VORBIS_COMMENT",
"CUESHEET",
"PICTURE"
};
FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[] = {
"Other",
"32x32 pixels 'file icon' (PNG only)",
"Other file icon",
"Cover (front)",
"Cover (back)",
"Leaflet page",
"Media (e.g. label side of CD)",
"Lead artist/lead performer/soloist",
"Artist/performer",
"Conductor",
"Band/Orchestra",
"Composer",
"Lyricist/text writer",
"Recording Location",
"During recording",
"During performance",
"Movie/video screen capture",
"A bright coloured fish",
"Illustration",
"Band/artist logotype",
"Publisher/Studio logotype"
};
FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(unsigned sample_rate)
{
if(sample_rate == 0 || sample_rate > FLAC__MAX_SAMPLE_RATE) {
return false;
}
else
return true;
}
FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(unsigned sample_rate)
{
if(
!FLAC__format_sample_rate_is_valid(sample_rate) ||
(
sample_rate >= (1u << 16) &&
!(sample_rate % 1000 == 0 || sample_rate % 10 == 0)
)
) {
return false;
}
else
return true;
}
/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table)
{
unsigned i;
FLAC__uint64 prev_sample_number = 0;
FLAC__bool got_prev = false;
FLAC__ASSERT(0 != seek_table);
for(i = 0; i < seek_table->num_points; i++) {
if(got_prev) {
if(
seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
seek_table->points[i].sample_number <= prev_sample_number
)
return false;
}
prev_sample_number = seek_table->points[i].sample_number;
got_prev = true;
}
return true;
}
/* used as the sort predicate for qsort() */
static int JUCE_CDECL seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r)
{
/* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */
if(l->sample_number == r->sample_number)
return 0;
else if(l->sample_number < r->sample_number)
return -1;
else
return 1;
}
/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
FLAC_API unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table)
{
unsigned i, j;
FLAC__bool first;
FLAC__ASSERT(0 != seek_table);
/* sort the seekpoints */
qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (JUCE_CDECL *)(const void *, const void *))seekpoint_compare_);
/* uniquify the seekpoints */
first = true;
for(i = j = 0; i < seek_table->num_points; i++) {
if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) {
if(!first) {
if(seek_table->points[i].sample_number == seek_table->points[j-1].sample_number)
continue;
}
}
first = false;
seek_table->points[j++] = seek_table->points[i];
}
for(i = j; i < seek_table->num_points; i++) {
seek_table->points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
seek_table->points[i].stream_offset = 0;
seek_table->points[i].frame_samples = 0;
}
return j;
}
/*
* also disallows non-shortest-form encodings, c.f.
* http://www.unicode.org/versions/corrigendum1.html
* and a more clear explanation at the end of this section:
* http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
*/
static FLaC__INLINE unsigned utf8len_(const FLAC__byte *utf8)
{
FLAC__ASSERT(0 != utf8);
if ((utf8[0] & 0x80) == 0) {
return 1;
}
else if ((utf8[0] & 0xE0) == 0xC0 && (utf8[1] & 0xC0) == 0x80) {
if ((utf8[0] & 0xFE) == 0xC0) /* overlong sequence check */
return 0;
return 2;
}
else if ((utf8[0] & 0xF0) == 0xE0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80) {
if (utf8[0] == 0xE0 && (utf8[1] & 0xE0) == 0x80) /* overlong sequence check */
return 0;
/* illegal surrogates check (U+D800...U+DFFF and U+FFFE...U+FFFF) */
if (utf8[0] == 0xED && (utf8[1] & 0xE0) == 0xA0) /* D800-DFFF */
return 0;
if (utf8[0] == 0xEF && utf8[1] == 0xBF && (utf8[2] & 0xFE) == 0xBE) /* FFFE-FFFF */
return 0;
return 3;
}
else if ((utf8[0] & 0xF8) == 0xF0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80) {
if (utf8[0] == 0xF0 && (utf8[1] & 0xF0) == 0x80) /* overlong sequence check */
return 0;
return 4;
}
else if ((utf8[0] & 0xFC) == 0xF8 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80) {
if (utf8[0] == 0xF8 && (utf8[1] & 0xF8) == 0x80) /* overlong sequence check */
return 0;
return 5;
}
else if ((utf8[0] & 0xFE) == 0xFC && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80 && (utf8[5] & 0xC0) == 0x80) {
if (utf8[0] == 0xFC && (utf8[1] & 0xFC) == 0x80) /* overlong sequence check */
return 0;
return 6;
}
else {
return 0;
}
}
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name)
{
char c;
for(c = *name; c; c = *(++name))
if(c < 0x20 || c == 0x3d || c > 0x7d)
return false;
return true;
}
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, unsigned length)
{
if(length == (unsigned)(-1)) {
while(*value) {
unsigned n = utf8len_(value);
if(n == 0)
return false;
value += n;
}
}
else {
const FLAC__byte *end = value + length;
while(value < end) {
unsigned n = utf8len_(value);
if(n == 0)
return false;
value += n;
}
if(value != end)
return false;
}
return true;
}
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, unsigned length)
{
const FLAC__byte *s, *end;
for(s = entry, end = s + length; s < end && *s != '='; s++) {
if(*s < 0x20 || *s > 0x7D)
return false;
}
if(s == end)
return false;
s++; /* skip '=' */
while(s < end) {
unsigned n = utf8len_(s);
if(n == 0)
return false;
s += n;
}
if(s != end)
return false;
return true;
}
/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation)
{
unsigned i, j;
if(check_cd_da_subset) {
if(cue_sheet->lead_in < 2 * 44100) {
if(violation) *violation = "CD-DA cue sheet must have a lead-in length of at least 2 seconds";
return false;
}
if(cue_sheet->lead_in % 588 != 0) {
if(violation) *violation = "CD-DA cue sheet lead-in length must be evenly divisible by 588 samples";
return false;
}
}
if(cue_sheet->num_tracks == 0) {
if(violation) *violation = "cue sheet must have at least one track (the lead-out)";
return false;
}
if(check_cd_da_subset && cue_sheet->tracks[cue_sheet->num_tracks-1].number != 170) {
if(violation) *violation = "CD-DA cue sheet must have a lead-out track number 170 (0xAA)";
return false;
}
for(i = 0; i < cue_sheet->num_tracks; i++) {
if(cue_sheet->tracks[i].number == 0) {
if(violation) *violation = "cue sheet may not have a track number 0";
return false;
}
if(check_cd_da_subset) {
if(!((cue_sheet->tracks[i].number >= 1 && cue_sheet->tracks[i].number <= 99) || cue_sheet->tracks[i].number == 170)) {
if(violation) *violation = "CD-DA cue sheet track number must be 1-99 or 170";
return false;
}
}
if(check_cd_da_subset && cue_sheet->tracks[i].offset % 588 != 0) {
if(violation) {
if(i == cue_sheet->num_tracks-1) /* the lead-out track... */
*violation = "CD-DA cue sheet lead-out offset must be evenly divisible by 588 samples";
else
*violation = "CD-DA cue sheet track offset must be evenly divisible by 588 samples";
}
return false;
}
if(i < cue_sheet->num_tracks - 1) {
if(cue_sheet->tracks[i].num_indices == 0) {
if(violation) *violation = "cue sheet track must have at least one index point";
return false;
}
if(cue_sheet->tracks[i].indices[0].number > 1) {
if(violation) *violation = "cue sheet track's first index number must be 0 or 1";
return false;
}
}
for(j = 0; j < cue_sheet->tracks[i].num_indices; j++) {
if(check_cd_da_subset && cue_sheet->tracks[i].indices[j].offset % 588 != 0) {
if(violation) *violation = "CD-DA cue sheet track index offset must be evenly divisible by 588 samples";
return false;
}
if(j > 0) {
if(cue_sheet->tracks[i].indices[j].number != cue_sheet->tracks[i].indices[j-1].number + 1) {
if(violation) *violation = "cue sheet track index numbers must increase by 1";
return false;
}
}
}
}
return true;
}
/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation)
{
char *p;
FLAC__byte *b;
for(p = picture->mime_type; *p; p++) {
if(*p < 0x20 || *p > 0x7e) {
if(violation) *violation = "MIME type string must contain only printable ASCII characters (0x20-0x7e)";
return false;
}
}
for(b = picture->description; *b; ) {
unsigned n = utf8len_(b);
if(n == 0) {
if(violation) *violation = "description string must be valid UTF-8";
return false;
}
b += n;
}
return true;
}
/*
* These routines are private to libFLAC
*/
unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order)
{
return
FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(
FLAC__format_get_max_rice_partition_order_from_blocksize(blocksize),
blocksize,
predictor_order
);
}
unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize)
{
unsigned max_rice_partition_order = 0;
while(!(blocksize & 1)) {
max_rice_partition_order++;
blocksize >>= 1;
}
return min(FLAC__MAX_RICE_PARTITION_ORDER, max_rice_partition_order);
}
unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned predictor_order)
{
unsigned max_rice_partition_order = limit;
while(max_rice_partition_order > 0 && (blocksize >> max_rice_partition_order) <= predictor_order)
max_rice_partition_order--;
FLAC__ASSERT(
(max_rice_partition_order == 0 && blocksize >= predictor_order) ||
(max_rice_partition_order > 0 && blocksize >> max_rice_partition_order > predictor_order)
);
return max_rice_partition_order;
}
void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object)
{
FLAC__ASSERT(0 != object);
object->parameters = 0;
object->raw_bits = 0;
object->capacity_by_order = 0;
}
void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object)
{
FLAC__ASSERT(0 != object);
if(0 != object->parameters)
free(object->parameters);
if(0 != object->raw_bits)
free(object->raw_bits);
FLAC__format_entropy_coding_method_partitioned_rice_contents_init(object);
}
FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, unsigned max_partition_order)
{
FLAC__ASSERT(0 != object);
FLAC__ASSERT(object->capacity_by_order > 0 || (0 == object->parameters && 0 == object->raw_bits));
if(object->capacity_by_order < max_partition_order) {
if(0 == (object->parameters = (unsigned*)realloc(object->parameters, sizeof(unsigned)*(1 << max_partition_order))))
return false;
if(0 == (object->raw_bits = (unsigned*)realloc(object->raw_bits, sizeof(unsigned)*(1 << max_partition_order))))
return false;
memset(object->raw_bits, 0, sizeof(unsigned)*(1 << max_partition_order));
object->capacity_by_order = max_partition_order;
}
return true;
}

+ 49
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/all.h View File

@@ -0,0 +1,49 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FLAC__PRIVATE__ALL_H
#define FLAC__PRIVATE__ALL_H
#include "bitmath.h"
#include "bitreader.h"
#include "bitwriter.h"
#include "cpu.h"
#include "crc.h"
#include "fixed.h"
#include "float.h"
#include "format.h"
#include "lpc.h"
#include "md5.h"
#include "memory.h"
#include "metadata.h"
#include "stream_encoder_framing.h"
#endif

+ 42
- 0
ports/radium-compressor/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitmath.h View File

@@ -0,0 +1,42 @@
/* libFLAC - Free Lossless Audio Codec library
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the Xiph.org Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FLAC__PRIVATE__BITMATH_H
#define FLAC__PRIVATE__BITMATH_H
#include "../../../ordinals.h"
unsigned FLAC__bitmath_ilog2(FLAC__uint32 v);
unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v);
unsigned FLAC__bitmath_silog2(int v);
unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v);
#endif

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save