/* Copyright (c) 2021 Alex Diener This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Alex Diener alex@ludobloom.com */ #include "audiosynth/AmplitudeEnvelope.h" #include "audiosynth/AmplitudeEnvelope_layered.h" #include "audiosynth/AmplitudeEnvelope_linearADSR.h" #include "audiosynth/AmplitudeEnvelope_pulse.h" #include "audiosynth/AmplitudeEnvelope_spline.h" #include "audiosynth/AmplitudeEnvelope_tremolo.h" #include "audiosynth/FrequencyCurve.h" #include "audiosynth/FrequencyCurve_layered.h" #include "audiosynth/FrequencyCurve_spline.h" #include "audiosynth/FrequencyCurve_stairstep.h" #include "audiosynth/FrequencyCurve_vibrato.h" #include "audiosynth/GeneralSynthConfiguration.h" #include "audiosynth/SignalFilter.h" #include "audiosynth/SignalFilter_bitcrush.h" #include "audiosynth/SignalFilter_compression.h" #include "audiosynth/SignalFilter_delay.h" #include "audiosynth/SignalFilter_distortion.h" #include "audiosynth/SynthPropertyController_ramp.h" #include "audiosynth/SynthPropertyController_sine.h" #include "audiosynth/WaveModifier.h" #include "audiosynth/WaveModifier_chord.h" #include "audiosynth/WaveModifier_distortion.h" #include "audiosynth/WaveModifier_harmonics.h" #include "audiosynth/WaveModifier_highLowpass.h" #include "audiosynth/WaveModifier_phaser.h" #include "audiosynth/WaveModifier_reset.h" #include "audiosynth/WaveModifier_ringModulation.h" #include "audiosynth/WaveModifier_sfxrHighLowpass.h" #include "audiosynth/WaveModifier_supersample.h" #include "audiosynth/WaveModifier_timeCurve.h" #include "audiosynth/WaveModifier_timeValueTransform.h" #include "audiosynth/WaveModifier_thinning.h" #include "audiosynth/WaveSampler.h" #include "audiosynth/WaveSampler_bitnoise.h" #include "audiosynth/WaveSampler_layered.h" #include "audiosynth/WaveSampler_modified.h" #include "audiosynth/WaveSampler_noise.h" #include "audiosynth/WaveSampler_pcmData.h" #include "audiosynth/WaveSampler_pinkNoise.h" #include "audiosynth/WaveSampler_pulse.h" #include "audiosynth/WaveSampler_sawtooth.h" #include "audiosynth/WaveSampler_sine.h" #include "audiosynth/WaveSampler_spike.h" #include "audiosynth/WaveSampler_spline.h" #include "audiosynth/WaveSampler_triangle.h" #include "utilities/IOUtilities.h" #include "stem_core.h" #include #define stemobject_implementation GeneralSynthConfiguration stemobject_vtable_begin(); stemobject_vtable_entry(dispose); stemobject_vtable_end(); GeneralSynthConfiguration * GeneralSynthConfiguration_create(void) { stemobject_create_implementation(init) } bool GeneralSynthConfiguration_init(GeneralSynthConfiguration * self) { call_super(init, self); self->trackCount = 0; self->tracks = NULL; return true; } void GeneralSynthConfiguration_dispose(GeneralSynthConfiguration * self) { for (unsigned int trackIndex = 0; trackIndex < self->trackCount; trackIndex++) { struct GeneralSynthConfiguration_track track = self->tracks[trackIndex]; GeneralSynthConfiguration_disposeAmplitudeParameters(track.amplitudeParameters); GeneralSynthConfiguration_disposeFrequencyParameters(track.frequencyParameters); GeneralSynthConfiguration_disposeWaveParameters(track.waveParameters); free(track.name); for (unsigned int filterIndex = 0; filterIndex < track.signalFilterCount; filterIndex++) { GeneralSynthConfiguration_disposeSignalFilterParameters(track.signalFilterParameters[filterIndex]); } free(track.signalFilterParameters); for (unsigned int controllerIndex = 0; controllerIndex < track.controllerCount; controllerIndex++) { GeneralSynthConfiguration_disposeSynthPropertyControllerParameters(track.controllerParameters[controllerIndex]); } free(track.controllerParameters); } free(self->tracks); call_super_virtual(dispose, self); } AudioSamplerParameters_multitrack * GeneralSynthConfiguration_createAudioSamplerParameters(GeneralSynthConfiguration * self) { struct AudioSamplerParameters_multitrack_track tracks[self->trackCount]; for (unsigned int trackIndex = 0; trackIndex < self->trackCount; trackIndex++) { struct GeneralSynthConfiguration_track track = self->tracks[trackIndex]; AmplitudeEnvelope * amplitudeEnvelope = GeneralSynthConfiguration_createAmplitudeEnvelopeFromParameters(track.amplitudeParameters); FrequencyCurve * frequencyCurve = GeneralSynthConfiguration_createFrequencyCurveFromParameters(track.frequencyParameters); WaveSampler * waveSampler = GeneralSynthConfiguration_createWaveSamplerFromParameters(track.waveParameters); FilterChain filterChain = FilterChain_empty; if (track.signalFilterCount > 0) { filterChain.signalFilterCount = track.signalFilterCount; filterChain.signalFilters = malloc(filterChain.signalFilterCount * sizeof(*filterChain.signalFilters)); for (unsigned int filterIndex = 0; filterIndex < track.signalFilterCount; filterIndex++) { filterChain.signalFilters[filterIndex] = GeneralSynthConfiguration_createSignalFilterFromParameters(track.signalFilterParameters[filterIndex]); } } SynthPropertyControllerList controllerList = SynthPropertyControllerList_empty; if (track.controllerCount > 0) { controllerList.controllerCount = track.controllerCount; controllerList.controllers = malloc(controllerList.controllerCount * sizeof(*controllerList.controllers)); for (unsigned int controllerIndex = 0; controllerIndex < track.controllerCount; controllerIndex++) { controllerList.controllers[controllerIndex] = GeneralSynthConfiguration_createSynthPropertyControllerFromParameters(track.controllerParameters[controllerIndex]); } } tracks[trackIndex].name = strdup(track.name); tracks[trackIndex].offset = track.offset; tracks[trackIndex].blend = track.blend; tracks[trackIndex].mute = track.mute; tracks[trackIndex].solo = track.solo; tracks[trackIndex].parameters = AudioSamplerParameters_generalSynth_create(waveSampler, frequencyCurve, amplitudeEnvelope, filterChain, controllerList, track.timingMode, track.length, track.amplitudeTimeAbsolute, track.frequencyTimeAbsolute); } return AudioSamplerParameters_multitrack_create(self->trackCount, tracks); } GeneralSynthConfiguration * GeneralSynthConfiguration_createFromAudioSamplerParameters(AudioSamplerParameters_multitrack * samplerParameters) { GeneralSynthConfiguration * self = GeneralSynthConfiguration_create(); self->trackCount = samplerParameters->trackCount; self->tracks = malloc(self->trackCount * sizeof(*self->tracks)); for (unsigned int trackIndex = 0; trackIndex < self->trackCount; trackIndex++) { struct AudioSamplerParameters_multitrack_track track = samplerParameters->tracks[trackIndex]; AudioSamplerParameters_generalSynth * trackParameters = (AudioSamplerParameters_generalSynth *) track.parameters; self->tracks[trackIndex].name = strdup(track.name); self->tracks[trackIndex].offset = track.offset; self->tracks[trackIndex].blend = track.blend; self->tracks[trackIndex].mute = track.mute; self->tracks[trackIndex].solo = track.solo; self->tracks[trackIndex].amplitudeParameters = GeneralSynthConfiguration_createAmplitudeParametersFromEnvelope(trackParameters->amplitudeEnvelope); self->tracks[trackIndex].frequencyParameters = GeneralSynthConfiguration_createFrequencyParametersFromCurve(trackParameters->frequencyCurve); self->tracks[trackIndex].waveParameters = GeneralSynthConfiguration_createWaveParametersFromSampler(trackParameters->waveSampler); self->tracks[trackIndex].signalFilterCount = trackParameters->filterChain.signalFilterCount; if (self->tracks[trackIndex].signalFilterCount == 0) { self->tracks[trackIndex].signalFilterParameters = NULL; } else { self->tracks[trackIndex].signalFilterParameters = malloc(self->tracks[trackIndex].signalFilterCount * sizeof(*self->tracks[trackIndex].signalFilterParameters)); for (unsigned int filterIndex = 0; filterIndex < self->tracks[trackIndex].signalFilterCount; filterIndex++) { self->tracks[trackIndex].signalFilterParameters[filterIndex] = GeneralSynthConfiguration_createSignalFilterParametersFromFilter(trackParameters->filterChain.signalFilters[filterIndex]); } } self->tracks[trackIndex].controllerCount = trackParameters->controllerList.controllerCount; if (self->tracks[trackIndex].controllerCount == 0) { self->tracks[trackIndex].controllerParameters = NULL; } else { self->tracks[trackIndex].controllerParameters = malloc(self->tracks[trackIndex].controllerCount * sizeof(*self->tracks[trackIndex].controllerParameters)); for (unsigned int controllerIndex = 0; controllerIndex < self->tracks[trackIndex].controllerCount; controllerIndex++) { self->tracks[trackIndex].controllerParameters[controllerIndex] = GeneralSynthConfiguration_createSynthPropertyControllerParametersFromController(trackParameters->controllerList.controllers[controllerIndex]); } } self->tracks[trackIndex].timingMode = trackParameters->timingMode; self->tracks[trackIndex].length = trackParameters->length; self->tracks[trackIndex].amplitudeTimeAbsolute = trackParameters->amplitudeTimeAbsolute; self->tracks[trackIndex].frequencyTimeAbsolute = trackParameters->frequencyTimeAbsolute; } return self; } GeneralSynthConfiguration * GeneralSynthConfiguration_deserialize(compat_type(DeserializationContext *) deserializationContext) { stemobject_deserialize_implementation(initFromSerializedData) } GeneralSynthConfiguration * GeneralSynthConfiguration_deserializeMinimal(compat_type(DeserializationContext *) deserializationContext, uint16_t formatVersion) { stemobject_deserialize_implementation(initFromSerializedDataMinimal, formatVersion) } static SplineInfo readSplineInfo(DeserializationContext * context) { SplineInfo spline; spline.xMax = call_virtual(readFloat, context, "x_max"); spline.yMin = call_virtual(readFloat, context, "y_min"); spline.yMax = call_virtual(readFloat, context, "y_max"); spline.sampleIterations = call_virtual(readUInt16, context, "sample_iterations"); spline.pointCount = call_virtual(beginArray, context, "points"); spline.points = malloc(spline.pointCount * sizeof(*spline.points)); for (unsigned int pointIndex = 0; pointIndex < spline.pointCount; pointIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(beginStructure, context, "position"); spline.points[pointIndex].position.x = call_virtual(readFloat, context, "x"); spline.points[pointIndex].position.y = call_virtual(readFloat, context, "y"); call_virtual(endStructure, context); call_virtual(beginStructure, context, "leading_control"); spline.points[pointIndex].leadingControlPoint.x = call_virtual(readFloat, context, "x"); spline.points[pointIndex].leadingControlPoint.y = call_virtual(readFloat, context, "y"); call_virtual(endStructure, context); call_virtual(beginStructure, context, "trailing_control"); spline.points[pointIndex].trailingControlPoint.x = call_virtual(readFloat, context, "x"); spline.points[pointIndex].trailingControlPoint.y = call_virtual(readFloat, context, "y"); call_virtual(endStructure, context); call_virtual(endStructure, context); } call_virtual(endArray, context); return spline; } #define TIMING_MODE_ENUM_VALUES { \ {"specify", SAMPLER_TIMING_SPECIFY_LENGTH}, \ {"amplitude", SAMPLER_TIMING_AMPLITUDE_LENGTH}, \ {"frequency", SAMPLER_TIMING_FREQUENCY_LENGTH}, \ {"wave", SAMPLER_TIMING_WAVE_LENGTH} \ } static void loadSerializedDataMinimal(GeneralSynthConfiguration * self, DeserializationContext * context, uint16_t formatVersion) { const uint16_t AMPLITUDE_FORMAT_VERSIONS[2] = {0, 1}; self->tracks = NULL; self->trackCount = call_virtual(beginArray, context, "tracks"); if (self->trackCount == 0) { context->status = 100; return; } self->tracks = calloc(self->trackCount, sizeof(*self->tracks)); for (unsigned int trackIndex = 0; trackIndex < self->trackCount; trackIndex++) { struct GeneralSynthConfiguration_track track; memset(&track, 0, sizeof(track)); call_virtual(beginStructure, context, NULL); track.name = strdup_nullSafe(call_virtual(readString, context, "name")); track.offset = call_virtual(readFloat, context, "offset"); track.blend = call_virtual(readFloat, context, "blend"); track.mute = call_virtual(readBoolean, context, "mute"); track.solo = call_virtual(readBoolean, context, "solo"); Serialization_enumKeyValue timingModeValues[] = TIMING_MODE_ENUM_VALUES; track.timingMode = call_virtual(readEnumeration, context, "timing_mode", sizeof_count(timingModeValues), timingModeValues); track.length = call_virtual(readFloat, context, "length"); track.amplitudeTimeAbsolute = call_virtual(readBoolean, context, "amp_absolute"); track.frequencyTimeAbsolute = call_virtual(readBoolean, context, "freq_absolute"); call_virtual(beginStructure, context, "amplitude"); GeneralSynthConfiguration_deserializeAmplitudeParametersMinimal(context, AMPLITUDE_FORMAT_VERSIONS[formatVersion], &track.amplitudeParameters); call_virtual(endStructure, context); call_virtual(beginStructure, context, "frequency"); GeneralSynthConfiguration_deserializeFrequencyParametersMinimal(context, 0, &track.frequencyParameters); call_virtual(endStructure, context); call_virtual(beginStructure, context, "wave"); GeneralSynthConfiguration_deserializeWaveParametersMinimal(context, 0, &track.waveParameters); call_virtual(endStructure, context); track.signalFilterCount = call_virtual(beginArray, context, "signal_filters"); if (track.signalFilterCount == 0) { track.signalFilterParameters = NULL; } else { track.signalFilterParameters = calloc(track.signalFilterCount, sizeof(*track.signalFilterParameters)); for (unsigned int filterIndex = 0; filterIndex < track.signalFilterCount; filterIndex++) { call_virtual(beginStructure, context, NULL); GeneralSynthConfiguration_deserializeSignalFilterParametersMinimal(context, 0, &track.signalFilterParameters[filterIndex]); call_virtual(endStructure, context); } } call_virtual(endArray, context); track.controllerCount = call_virtual(beginArray, context, "property_controllers"); if (track.controllerCount == 0) { track.controllerParameters = NULL; } else { track.controllerParameters = calloc(track.controllerCount, sizeof(*track.controllerParameters)); for (unsigned int controllerIndex = 0; controllerIndex < track.controllerCount; controllerIndex++) { call_virtual(beginStructure, context, NULL); GeneralSynthConfiguration_deserializeSynthPropertyControllerParametersMinimal(context, 0, &track.controllerParameters[controllerIndex]); call_virtual(endStructure, context); } } call_virtual(endArray, context); call_virtual(endStructure, context); self->tracks[trackIndex] = track; } call_virtual(endArray, context); } bool GeneralSynthConfiguration_initFromSerializedData(GeneralSynthConfiguration * self, compat_type(DeserializationContext *) deserializationContext) { DeserializationContext * context = deserializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_formatType); const char * formatType = call_virtual(readString, context, "format_type"); if (formatType == NULL || strcmp(formatType, GeneralSynthConfiguration_formatType)) { return false; } uint16_t formatVersion = call_virtual(readUInt16, context, "format_version"); if (formatVersion > GeneralSynthConfiguration_formatVersion) { return false; } call_super(init, self); self->trackCount = 0; self->tracks = NULL; loadSerializedDataMinimal(self, context, formatVersion); call_virtual(endStructure, context); if (context->status != SERIALIZATION_ERROR_OK) { call_virtual(dispose, self); return false; } return true; } bool GeneralSynthConfiguration_initFromSerializedDataMinimal(GeneralSynthConfiguration * self, compat_type(DeserializationContext *) deserializationContext, uint16_t formatVersion) { DeserializationContext * context = deserializationContext; call_super(init, self); loadSerializedDataMinimal(self, context, formatVersion); if (context->status != SERIALIZATION_ERROR_OK) { call_virtual(dispose, self); return false; } return true; } static void writeSplineInfo(SerializationContext * context, SplineInfo spline) { call_virtual(writeFloat, context, "x_max", spline.xMax); call_virtual(writeFloat, context, "y_min", spline.yMin); call_virtual(writeFloat, context, "y_max", spline.yMax); call_virtual(writeUInt16, context, "sample_iterations", spline.sampleIterations); call_virtual(beginArray, context, "points"); for (unsigned int pointIndex = 0; pointIndex < spline.pointCount; pointIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(beginStructure, context, "position"); call_virtual(writeFloat, context, "x", spline.points[pointIndex].position.x); call_virtual(writeFloat, context, "y", spline.points[pointIndex].position.y); call_virtual(endStructure, context); call_virtual(beginStructure, context, "leading_control"); call_virtual(writeFloat, context, "x", spline.points[pointIndex].leadingControlPoint.x); call_virtual(writeFloat, context, "y", spline.points[pointIndex].leadingControlPoint.y); call_virtual(endStructure, context); call_virtual(beginStructure, context, "trailing_control"); call_virtual(writeFloat, context, "x", spline.points[pointIndex].trailingControlPoint.x); call_virtual(writeFloat, context, "y", spline.points[pointIndex].trailingControlPoint.y); call_virtual(endStructure, context); call_virtual(endStructure, context); } call_virtual(endArray, context); } void GeneralSynthConfiguration_serialize(GeneralSynthConfiguration * self, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_formatType); call_virtual(writeString, context, "format_type", GeneralSynthConfiguration_formatType); call_virtual(writeUInt16, context, "format_version", GeneralSynthConfiguration_formatVersion); GeneralSynthConfiguration_serializeMinimal(self, context); call_virtual(endStructure, context); } void GeneralSynthConfiguration_serializeMinimal(GeneralSynthConfiguration * self, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(beginArray, context, "tracks"); for (unsigned int trackIndex = 0; trackIndex < self->trackCount; trackIndex++) { struct GeneralSynthConfiguration_track track = self->tracks[trackIndex]; call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "name", track.name); call_virtual(writeFloat, context, "offset", track.offset); call_virtual(writeFloat, context, "blend", track.blend); call_virtual(writeBoolean, context, "mute", track.mute); call_virtual(writeBoolean, context, "solo", track.solo); Serialization_enumKeyValue timingModeValues[] = TIMING_MODE_ENUM_VALUES; call_virtual(writeEnumeration, context, "timing_mode", track.timingMode, sizeof_count(timingModeValues), timingModeValues); call_virtual(writeFloat, context, "length", track.length); call_virtual(writeBoolean, context, "amp_absolute", track.amplitudeTimeAbsolute); call_virtual(writeBoolean, context, "freq_absolute", track.frequencyTimeAbsolute); call_virtual(beginStructure, context, "amplitude"); GeneralSynthConfiguration_serializeAmplitudeParametersMinimal(track.amplitudeParameters, context); call_virtual(endStructure, context); call_virtual(beginStructure, context, "frequency"); GeneralSynthConfiguration_serializeFrequencyParametersMinimal(track.frequencyParameters, context); call_virtual(endStructure, context); call_virtual(beginStructure, context, "wave"); GeneralSynthConfiguration_serializeWaveParametersMinimal(track.waveParameters, context); call_virtual(endStructure, context); call_virtual(beginArray, context, "signal_filters"); for (unsigned int filterIndex = 0; filterIndex < track.signalFilterCount; filterIndex++) { call_virtual(beginStructure, context, NULL); GeneralSynthConfiguration_serializeSignalFilterParametersMinimal(track.signalFilterParameters[filterIndex], context); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "property_controllers"); for (unsigned int controllerIndex = 0; controllerIndex < track.controllerCount; controllerIndex++) { call_virtual(beginStructure, context, NULL); GeneralSynthConfiguration_serializeSynthPropertyControllerParametersMinimal(track.controllerParameters[controllerIndex], context); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(endStructure, context); } call_virtual(endArray, context); } struct GeneralSynthConfiguration_amplitudeParameters GeneralSynthConfiguration_createAmplitudeParametersFromEnvelope(compat_type(AmplitudeEnvelope *) amplitudeEnvelopeUntyped) { AmplitudeEnvelope * amplitudeEnvelope = amplitudeEnvelopeUntyped; struct GeneralSynthConfiguration_amplitudeParameters parameters; parameters.type = getAmplitudeType(amplitudeEnvelope); switch (parameters.type) { case AMPLITUDE_TYPE_FLAT: parameters.info.flat.baseAmplitude = amplitudeEnvelope->baseAmplitude; break; case AMPLITUDE_TYPE_ADSR: { AmplitudeEnvelope_linearADSR * amplitudeEnvelopeTyped = (AmplitudeEnvelope_linearADSR *) amplitudeEnvelope; parameters.info.linearADSR.peakAmplitude = amplitudeEnvelopeTyped->baseAmplitude; parameters.info.linearADSR.sustainAmplitude = amplitudeEnvelopeTyped->sustainAmplitude; parameters.info.linearADSR.punchAmplitude = amplitudeEnvelopeTyped->punchAmplitude; parameters.info.linearADSR.attackTime = amplitudeEnvelopeTyped->attackTime; parameters.info.linearADSR.decayTime = amplitudeEnvelopeTyped->decayTime; parameters.info.linearADSR.sustainTime = amplitudeEnvelopeTyped->sustainTime; parameters.info.linearADSR.releaseTime = amplitudeEnvelopeTyped->releaseTime; break; } case AMPLITUDE_TYPE_PULSE: { AmplitudeEnvelope_pulse * amplitudeEnvelopeTyped = (AmplitudeEnvelope_pulse *) amplitudeEnvelope; parameters.info.pulse.cycleCount = amplitudeEnvelopeTyped->cycleCount; parameters.info.pulse.maxAmplitude = amplitudeEnvelopeTyped->baseAmplitude; parameters.info.pulse.minAmplitude = amplitudeEnvelopeTyped->minAmplitude; parameters.info.pulse.startPhase = amplitudeEnvelopeTyped->startPhase; parameters.info.pulse.attackTime = amplitudeEnvelopeTyped->attackTime; parameters.info.pulse.sustainTime = amplitudeEnvelopeTyped->sustainTime; parameters.info.pulse.releaseTime = amplitudeEnvelopeTyped->releaseTime; parameters.info.pulse.restTime = amplitudeEnvelopeTyped->restTime; break; } case AMPLITUDE_TYPE_SPLINE: { AmplitudeEnvelope_spline * amplitudeEnvelopeTyped = (AmplitudeEnvelope_spline *) amplitudeEnvelope; parameters.info.spline.spline = copySplineInfo(&litudeEnvelopeTyped->spline); parameters.info.spline.length = amplitudeEnvelopeTyped->length; break; } case AMPLITUDE_TYPE_TREMOLO: { AmplitudeEnvelope_tremolo * amplitudeEnvelopeTyped = (AmplitudeEnvelope_tremolo *) amplitudeEnvelope; parameters.info.tremolo.baseAmplitude = amplitudeEnvelopeTyped->baseAmplitude; parameters.info.tremolo.strength = amplitudeEnvelopeTyped->strength; parameters.info.tremolo.speed = amplitudeEnvelopeTyped->speed; parameters.info.tremolo.phase = amplitudeEnvelopeTyped->phase; parameters.info.tremolo.length = amplitudeEnvelopeTyped->length; break; } case AMPLITUDE_TYPE_LAYERED: { AmplitudeEnvelope_layered * amplitudeEnvelopeTyped = (AmplitudeEnvelope_layered *) amplitudeEnvelope; parameters.info.layered.baseAmplitude = amplitudeEnvelopeTyped->baseAmplitude; parameters.info.layered.blendMode = amplitudeEnvelopeTyped->blendMode; parameters.info.layered.layerCount = amplitudeEnvelopeTyped->layerCount; parameters.info.layered.layers = malloc(parameters.info.layered.layerCount * sizeof(*parameters.info.layered.layers)); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { parameters.info.layered.layers[layerIndex].blend = amplitudeEnvelopeTyped->layers[layerIndex].blend; parameters.info.layered.layers[layerIndex].mute = amplitudeEnvelopeTyped->layers[layerIndex].mute; parameters.info.layered.layers[layerIndex].solo = amplitudeEnvelopeTyped->layers[layerIndex].solo; parameters.info.layered.layers[layerIndex].parameters = GeneralSynthConfiguration_createAmplitudeParametersFromEnvelope(amplitudeEnvelopeTyped->layers[layerIndex].envelope); } break; } } return parameters; } AmplitudeEnvelope * GeneralSynthConfiguration_createAmplitudeEnvelopeFromParameters(struct GeneralSynthConfiguration_amplitudeParameters parameters) { switch (parameters.type) { case AMPLITUDE_TYPE_FLAT: return (AmplitudeEnvelope *) AmplitudeEnvelope_create(parameters.info.flat.baseAmplitude, parameters.info.flat.length); case AMPLITUDE_TYPE_ADSR: return (AmplitudeEnvelope *) AmplitudeEnvelope_linearADSR_create(parameters.info.linearADSR.peakAmplitude, parameters.info.linearADSR.sustainAmplitude, parameters.info.linearADSR.punchAmplitude, parameters.info.linearADSR.attackTime, parameters.info.linearADSR.decayTime, parameters.info.linearADSR.sustainTime, parameters.info.linearADSR.releaseTime); case AMPLITUDE_TYPE_PULSE: return (AmplitudeEnvelope *) AmplitudeEnvelope_pulse_create(parameters.info.pulse.cycleCount, parameters.info.pulse.maxAmplitude, parameters.info.pulse.minAmplitude, parameters.info.pulse.startPhase, parameters.info.pulse.attackTime, parameters.info.pulse.sustainTime, parameters.info.pulse.releaseTime, parameters.info.pulse.restTime); case AMPLITUDE_TYPE_SPLINE: return (AmplitudeEnvelope *) AmplitudeEnvelope_spline_create(copySplineInfo(¶meters.info.spline.spline), parameters.info.spline.length); case AMPLITUDE_TYPE_TREMOLO: return (AmplitudeEnvelope *) AmplitudeEnvelope_tremolo_create(parameters.info.tremolo.baseAmplitude, parameters.info.tremolo.strength, parameters.info.tremolo.speed, parameters.info.tremolo.phase, parameters.info.tremolo.length); case AMPLITUDE_TYPE_LAYERED: { struct AmplitudeEnvelope_layered_layer layers[parameters.info.layered.layerCount]; for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { layers[layerIndex].blend = parameters.info.layered.layers[layerIndex].blend; layers[layerIndex].mute = parameters.info.layered.layers[layerIndex].mute; layers[layerIndex].solo = parameters.info.layered.layers[layerIndex].solo; layers[layerIndex].envelope = GeneralSynthConfiguration_createAmplitudeEnvelopeFromParameters(parameters.info.layered.layers[layerIndex].parameters); } return (AmplitudeEnvelope *) AmplitudeEnvelope_layered_create(parameters.info.layered.baseAmplitude, parameters.info.layered.blendMode, parameters.info.layered.layerCount, layers); } } return NULL; } void GeneralSynthConfiguration_serializeAmplitudeParameters(struct GeneralSynthConfiguration_amplitudeParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_amplitude_formatType); call_virtual(writeString, context, "format_type", GeneralSynthConfiguration_amplitude_formatType); call_virtual(writeUInt16, context, "format_version", GeneralSynthConfiguration_amplitude_formatVersion); GeneralSynthConfiguration_serializeAmplitudeParametersMinimal(parameters, context); call_virtual(endStructure, context); } #define AMPLITUDE_TYPE_ENUM_VALUES { \ {"flat", AMPLITUDE_TYPE_FLAT}, \ {"linear_adsr", AMPLITUDE_TYPE_ADSR}, \ {"pulse", AMPLITUDE_TYPE_PULSE}, \ {"spline", AMPLITUDE_TYPE_SPLINE}, \ {"tremolo", AMPLITUDE_TYPE_TREMOLO}, \ {"layered", AMPLITUDE_TYPE_LAYERED} \ } #define AMPLITUDE_BLEND_MODE_ENUM_VALUES { \ {"add", AmplitudeEnvelope_layered_add}, \ {"multiply", AmplitudeEnvelope_layered_multiply}, \ {"average", AmplitudeEnvelope_layered_average}, \ {"min", AmplitudeEnvelope_layered_min}, \ {"max", AmplitudeEnvelope_layered_max} \ } void GeneralSynthConfiguration_serializeAmplitudeParametersMinimal(struct GeneralSynthConfiguration_amplitudeParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; Serialization_enumKeyValue amplitudeTypeValues[] = AMPLITUDE_TYPE_ENUM_VALUES; call_virtual(writeEnumeration, context, "type", parameters.type, sizeof_count(amplitudeTypeValues), amplitudeTypeValues); switch (parameters.type) { case AMPLITUDE_TYPE_FLAT: call_virtual(writeFloat, context, "base_amplitude", parameters.info.flat.baseAmplitude); call_virtual(writeFloat, context, "length", parameters.info.flat.length); break; case AMPLITUDE_TYPE_ADSR: call_virtual(writeFloat, context, "peak_amplitude", parameters.info.linearADSR.peakAmplitude); call_virtual(writeFloat, context, "sustain_amplitude", parameters.info.linearADSR.sustainAmplitude); call_virtual(writeFloat, context, "punch", parameters.info.linearADSR.punchAmplitude); call_virtual(writeFloat, context, "attack_time", parameters.info.linearADSR.attackTime); call_virtual(writeFloat, context, "decay_time", parameters.info.linearADSR.decayTime); call_virtual(writeFloat, context, "sustain_time", parameters.info.linearADSR.sustainTime); call_virtual(writeFloat, context, "release_time", parameters.info.linearADSR.releaseTime); break; case AMPLITUDE_TYPE_PULSE: call_virtual(writeFloat, context, "max_amplitude", parameters.info.pulse.maxAmplitude); call_virtual(writeFloat, context, "min_amplitude", parameters.info.pulse.minAmplitude); call_virtual(writeFloat, context, "start_phase", parameters.info.pulse.startPhase); call_virtual(writeFloat, context, "attack_time", parameters.info.pulse.attackTime); call_virtual(writeFloat, context, "sustain_time", parameters.info.pulse.sustainTime); call_virtual(writeFloat, context, "release_time", parameters.info.pulse.releaseTime); call_virtual(writeFloat, context, "rest_time", parameters.info.pulse.restTime); call_virtual(writeFloat, context, "cycle_count", parameters.info.pulse.cycleCount); break; case AMPLITUDE_TYPE_SPLINE: call_virtual(beginStructure, context, "spline"); writeSplineInfo(context, parameters.info.spline.spline); call_virtual(endStructure, context); call_virtual(writeFloat, context, "length", parameters.info.spline.length); break; case AMPLITUDE_TYPE_TREMOLO: call_virtual(writeFloat, context, "base_amplitude", parameters.info.tremolo.baseAmplitude); call_virtual(writeFloat, context, "strength", parameters.info.tremolo.strength); call_virtual(writeFloat, context, "speed", parameters.info.tremolo.speed); call_virtual(writeFloat, context, "phase", parameters.info.tremolo.phase); call_virtual(writeFloat, context, "length", parameters.info.tremolo.length); break; case AMPLITUDE_TYPE_LAYERED: { call_virtual(writeFloat, context, "base_amplitude", parameters.info.layered.baseAmplitude); Serialization_enumKeyValue blendModeValues[] = AMPLITUDE_BLEND_MODE_ENUM_VALUES; call_virtual(writeEnumeration, context, "blend_mode", parameters.info.layered.blendMode, sizeof_count(blendModeValues), blendModeValues); call_virtual(beginArray, context, "layers"); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeFloat, context, "blend", parameters.info.layered.layers[layerIndex].blend); call_virtual(writeBoolean, context, "mute", parameters.info.layered.layers[layerIndex].mute); call_virtual(writeBoolean, context, "solo", parameters.info.layered.layers[layerIndex].solo); GeneralSynthConfiguration_serializeAmplitudeParametersMinimal(parameters.info.layered.layers[layerIndex].parameters, context); call_virtual(endStructure, context); } call_virtual(endArray, context); break; } } } bool GeneralSynthConfiguration_deserializeAmplitudeParameters(compat_type(DeserializationContext *) deserializationContext, struct GeneralSynthConfiguration_amplitudeParameters * outParameters) { DeserializationContext * context = deserializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_amplitude_formatType); const char * formatType = call_virtual(readString, context, "format_type"); if (formatType == NULL || strcmp(formatType, GeneralSynthConfiguration_amplitude_formatType)) { return false; } uint16_t formatVersion = call_virtual(readUInt16, context, "format_version"); if (formatVersion > GeneralSynthConfiguration_amplitude_formatVersion) { return false; } bool success = GeneralSynthConfiguration_deserializeAmplitudeParametersMinimal(context, formatVersion, outParameters); call_virtual(endStructure, context); return success; } bool GeneralSynthConfiguration_deserializeAmplitudeParametersMinimal(compat_type(DeserializationContext *) deserializationContext, uint16_t formatVersion, struct GeneralSynthConfiguration_amplitudeParameters * outParameters) { DeserializationContext * context = deserializationContext; struct GeneralSynthConfiguration_amplitudeParameters parameters; Serialization_enumKeyValue amplitudeTypeValues[] = AMPLITUDE_TYPE_ENUM_VALUES; parameters.type = call_virtual(readEnumeration, context, "type", sizeof_count(amplitudeTypeValues), amplitudeTypeValues); switch (parameters.type) { case AMPLITUDE_TYPE_FLAT: parameters.info.flat.baseAmplitude = call_virtual(readFloat, context, "base_amplitude"); if (formatVersion > 0) { parameters.info.flat.length = call_virtual(readFloat, context, "length"); } else { parameters.info.flat.length = 1.0f; } break; case AMPLITUDE_TYPE_ADSR: parameters.info.linearADSR.peakAmplitude = call_virtual(readFloat, context, "peak_amplitude"); parameters.info.linearADSR.sustainAmplitude = call_virtual(readFloat, context, "sustain_amplitude"); parameters.info.linearADSR.punchAmplitude = call_virtual(readFloat, context, "punch"); parameters.info.linearADSR.attackTime = call_virtual(readFloat, context, "attack_time"); parameters.info.linearADSR.decayTime = call_virtual(readFloat, context, "decay_time"); parameters.info.linearADSR.sustainTime = call_virtual(readFloat, context, "sustain_time"); parameters.info.linearADSR.releaseTime = call_virtual(readFloat, context, "release_time"); break; case AMPLITUDE_TYPE_PULSE: parameters.info.pulse.maxAmplitude = call_virtual(readFloat, context, "max_amplitude"); parameters.info.pulse.minAmplitude = call_virtual(readFloat, context, "min_amplitude"); parameters.info.pulse.startPhase = call_virtual(readFloat, context, "start_phase"); parameters.info.pulse.attackTime = call_virtual(readFloat, context, "attack_time"); parameters.info.pulse.sustainTime = call_virtual(readFloat, context, "sustain_time"); parameters.info.pulse.releaseTime = call_virtual(readFloat, context, "release_time"); parameters.info.pulse.restTime = call_virtual(readFloat, context, "rest_time"); parameters.info.pulse.cycleCount = call_virtual(readFloat, context, "cycle_count"); break; case AMPLITUDE_TYPE_SPLINE: call_virtual(beginStructure, context, "spline"); parameters.info.spline.spline = readSplineInfo(context); if (formatVersion > 0) { parameters.info.spline.length = call_virtual(readFloat, context, "length"); } else { parameters.info.spline.length = 1.0f; } call_virtual(endStructure, context); break; case AMPLITUDE_TYPE_TREMOLO: parameters.info.tremolo.baseAmplitude = call_virtual(readFloat, context, "base_amplitude"); parameters.info.tremolo.strength = call_virtual(readFloat, context, "strength"); parameters.info.tremolo.speed = call_virtual(readFloat, context, "speed"); parameters.info.tremolo.phase = call_virtual(readFloat, context, "phase"); if (formatVersion > 0) { parameters.info.tremolo.length = call_virtual(readFloat, context, "length"); } else { parameters.info.tremolo.length = 1.0f; } break; case AMPLITUDE_TYPE_LAYERED: { parameters.info.layered.baseAmplitude = call_virtual(readFloat, context, "base_amplitude"); Serialization_enumKeyValue blendModeValues[] = AMPLITUDE_BLEND_MODE_ENUM_VALUES; parameters.info.layered.blendMode = call_virtual(readEnumeration, context, "blend_mode", sizeof_count(blendModeValues), blendModeValues); parameters.info.layered.layerCount = call_virtual(beginArray, context, "layers"); parameters.info.layered.layers = calloc(parameters.info.layered.layerCount, sizeof(*parameters.info.layered.layers)); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { call_virtual(beginStructure, context, NULL); parameters.info.layered.layers[layerIndex].blend = call_virtual(readFloat, context, "blend"); parameters.info.layered.layers[layerIndex].mute = call_virtual(readBoolean, context, "mute"); parameters.info.layered.layers[layerIndex].solo = call_virtual(readBoolean, context, "solo"); GeneralSynthConfiguration_deserializeAmplitudeParametersMinimal(context, formatVersion, ¶meters.info.layered.layers[layerIndex].parameters); call_virtual(endStructure, context); } call_virtual(endArray, context); break; } } if (context->status != SERIALIZATION_ERROR_OK) { GeneralSynthConfiguration_disposeAmplitudeParameters(parameters); return false; } *outParameters = parameters; return true; } void GeneralSynthConfiguration_disposeAmplitudeParameters(struct GeneralSynthConfiguration_amplitudeParameters parameters) { switch (parameters.type) { case AMPLITUDE_TYPE_FLAT: case AMPLITUDE_TYPE_ADSR: case AMPLITUDE_TYPE_PULSE: case AMPLITUDE_TYPE_TREMOLO: break; case AMPLITUDE_TYPE_SPLINE: disposeSplineInfo(¶meters.info.spline.spline); break; case AMPLITUDE_TYPE_LAYERED: for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { GeneralSynthConfiguration_disposeAmplitudeParameters(parameters.info.layered.layers[layerIndex].parameters); } free(parameters.info.layered.layers); break; } } GeneralSynthConfiguration_amplitudeType getAmplitudeType(AmplitudeEnvelope * amplitudeEnvelope) { if (StemObject_isExactClass(amplitudeEnvelope, &AmplitudeEnvelope_class)) { return AMPLITUDE_TYPE_FLAT; } if (StemObject_isExactClass(amplitudeEnvelope, &AmplitudeEnvelope_linearADSR_class)) { return AMPLITUDE_TYPE_ADSR; } if (StemObject_isExactClass(amplitudeEnvelope, &AmplitudeEnvelope_pulse_class)) { return AMPLITUDE_TYPE_PULSE; } if (StemObject_isExactClass(amplitudeEnvelope, &AmplitudeEnvelope_spline_class)) { return AMPLITUDE_TYPE_SPLINE; } if (StemObject_isExactClass(amplitudeEnvelope, &AmplitudeEnvelope_tremolo_class)) { return AMPLITUDE_TYPE_TREMOLO; } if (StemObject_isExactClass(amplitudeEnvelope, &AmplitudeEnvelope_layered_class)) { return AMPLITUDE_TYPE_LAYERED; } #ifdef DEBUG fprintf(stderr, "Warning: Unknown amplitude envelope class %p passed to getAmplitudeType\n", amplitudeEnvelope->vtable); #endif return AMPLITUDE_TYPE_FLAT; } const char * getAmplitudeEnvelopeHumanReadableName(GeneralSynthConfiguration_amplitudeType type) { switch (type) { case AMPLITUDE_TYPE_FLAT: return "Flat"; case AMPLITUDE_TYPE_ADSR: return "Linear ADSR"; case AMPLITUDE_TYPE_PULSE: return "Pulse"; case AMPLITUDE_TYPE_SPLINE: return "Spline"; case AMPLITUDE_TYPE_TREMOLO: return "Tremolo"; case AMPLITUDE_TYPE_LAYERED: return "Layered"; } return "(unknown)"; } struct GeneralSynthConfiguration_frequencyParameters GeneralSynthConfiguration_createFrequencyParametersFromCurve(compat_type(FrequencyCurve *) frequencyCurveUntyped) { FrequencyCurve * frequencyCurve = frequencyCurveUntyped; struct GeneralSynthConfiguration_frequencyParameters parameters; parameters.type = getFrequencyType(frequencyCurve); switch (parameters.type) { case FREQUENCY_TYPE_FLAT: parameters.info.flat.baseValue = frequencyCurve->baseValue; break; case FREQUENCY_TYPE_RAMP: { FrequencyCurve_ramp * frequencyCurveTyped = (FrequencyCurve_ramp *) frequencyCurve; parameters.info.ramp.baseValue = frequencyCurveTyped->baseValue; parameters.info.ramp.linearRamp = frequencyCurveTyped->linearRamp; parameters.info.ramp.curvedRamp = frequencyCurveTyped->curvedRamp; parameters.info.ramp.onset = frequencyCurveTyped->onset; parameters.info.ramp.endpoint = frequencyCurveTyped->endpoint; parameters.info.ramp.resetPoint = frequencyCurveTyped->resetPoint; parameters.info.ramp.boundType = frequencyCurveTyped->boundType; break; } case FREQUENCY_TYPE_STAIRSTEP: { FrequencyCurve_stairstep * frequencyCurveTyped = (FrequencyCurve_stairstep *) frequencyCurve; parameters.info.stairstep.baseValue = frequencyCurveTyped->baseValue; parameters.info.stairstep.stepCount = frequencyCurveTyped->stepCount; parameters.info.stairstep.steps = memdup(frequencyCurveTyped->steps, parameters.info.stairstep.stepCount * sizeof(*parameters.info.stairstep.steps)); parameters.info.stairstep.repeatStartIndex = frequencyCurveTyped->repeatStartIndex; parameters.info.stairstep.repeatCount = frequencyCurveTyped->repeatCount; break; } case FREQUENCY_TYPE_SPLINE: { FrequencyCurve_spline * frequencyCurveTyped = (FrequencyCurve_spline *) frequencyCurve; parameters.info.spline.baseValue = frequencyCurveTyped->baseValue; parameters.info.spline.spline = copySplineInfo(&frequencyCurveTyped->spline); break; } case FREQUENCY_TYPE_VIBRATO: { FrequencyCurve_vibrato * frequencyCurveTyped = (FrequencyCurve_vibrato *) frequencyCurve; parameters.info.vibrato.baseValue = frequencyCurveTyped->baseValue; parameters.info.vibrato.strength = frequencyCurveTyped->strength; parameters.info.vibrato.speed = frequencyCurveTyped->speed; parameters.info.vibrato.phase = frequencyCurveTyped->phase; break; } case FREQUENCY_TYPE_LAYERED: { FrequencyCurve_layered * frequencyCurveTyped = (FrequencyCurve_layered *) frequencyCurve; parameters.info.layered.baseValue = frequencyCurveTyped->baseValue; parameters.info.layered.blendMode = frequencyCurveTyped->blendMode; parameters.info.layered.layerCount = frequencyCurveTyped->layerCount; parameters.info.layered.layers = malloc(parameters.info.layered.layerCount * sizeof(*parameters.info.layered.layers)); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { parameters.info.layered.layers[layerIndex].blend = frequencyCurveTyped->layers[layerIndex].blend; parameters.info.layered.layers[layerIndex].mute = frequencyCurveTyped->layers[layerIndex].mute; parameters.info.layered.layers[layerIndex].solo = frequencyCurveTyped->layers[layerIndex].solo; parameters.info.layered.layers[layerIndex].parameters = GeneralSynthConfiguration_createFrequencyParametersFromCurve(frequencyCurveTyped->layers[layerIndex].curve); } break; } } return parameters; } FrequencyCurve * GeneralSynthConfiguration_createFrequencyCurveFromParameters(struct GeneralSynthConfiguration_frequencyParameters parameters) { switch (parameters.type) { case FREQUENCY_TYPE_FLAT: return (FrequencyCurve *) FrequencyCurve_create(parameters.info.flat.baseValue); case FREQUENCY_TYPE_RAMP: return (FrequencyCurve *) FrequencyCurve_ramp_create(parameters.info.ramp.baseValue, parameters.info.ramp.linearRamp, parameters.info.ramp.curvedRamp, parameters.info.ramp.onset, parameters.info.ramp.endpoint, parameters.info.ramp.resetPoint, parameters.info.ramp.boundType); case FREQUENCY_TYPE_STAIRSTEP: return (FrequencyCurve *) FrequencyCurve_stairstep_create(parameters.info.stairstep.baseValue, parameters.info.stairstep.stepCount, parameters.info.stairstep.steps, parameters.info.stairstep.repeatStartIndex, parameters.info.stairstep.repeatCount); case FREQUENCY_TYPE_SPLINE: return (FrequencyCurve *) FrequencyCurve_spline_create(parameters.info.spline.baseValue, copySplineInfo(¶meters.info.spline.spline)); case FREQUENCY_TYPE_VIBRATO: return (FrequencyCurve *) FrequencyCurve_vibrato_create(parameters.info.vibrato.baseValue, parameters.info.vibrato.strength, parameters.info.vibrato.speed, parameters.info.vibrato.phase); case FREQUENCY_TYPE_LAYERED: { struct FrequencyCurve_layered_layer layers[parameters.info.layered.layerCount]; for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { layers[layerIndex].blend = parameters.info.layered.layers[layerIndex].blend; layers[layerIndex].mute = parameters.info.layered.layers[layerIndex].mute; layers[layerIndex].solo = parameters.info.layered.layers[layerIndex].solo; layers[layerIndex].curve = GeneralSynthConfiguration_createFrequencyCurveFromParameters(parameters.info.layered.layers[layerIndex].parameters); } return (FrequencyCurve *) FrequencyCurve_layered_create(parameters.info.layered.baseValue, parameters.info.layered.blendMode, parameters.info.layered.layerCount, layers); } } return NULL; } void GeneralSynthConfiguration_serializeFrequencyParameters(struct GeneralSynthConfiguration_frequencyParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_frequency_formatType); call_virtual(writeString, context, "format_type", GeneralSynthConfiguration_frequency_formatType); call_virtual(writeUInt16, context, "format_version", GeneralSynthConfiguration_frequency_formatVersion); GeneralSynthConfiguration_serializeFrequencyParametersMinimal(parameters, context); call_virtual(endStructure, context); } #define FREQUENCY_TYPE_ENUM_VALUES { \ {"flat", FREQUENCY_TYPE_FLAT}, \ {"stairstep", FREQUENCY_TYPE_STAIRSTEP}, \ {"ramp", FREQUENCY_TYPE_RAMP}, \ {"spline", FREQUENCY_TYPE_SPLINE}, \ {"layered", FREQUENCY_TYPE_LAYERED}, \ {"vibrato", FREQUENCY_TYPE_VIBRATO} \ } #define FREQUENCY_BOUND_TYPE_ENUM_VALUES { \ {"reset", RAMP_RESET}, \ {"clamp", RAMP_CLAMP}, \ {"extrapolate", RAMP_EXTRAPOLATE} \ } #define FREQUENCY_BLEND_MODE_ENUM_VALUES { \ {"add", FrequencyCurve_layered_add}, \ {"average", FrequencyCurve_layered_average}, \ {"min", FrequencyCurve_layered_min}, \ {"max", FrequencyCurve_layered_max} \ } void GeneralSynthConfiguration_serializeFrequencyParametersMinimal(struct GeneralSynthConfiguration_frequencyParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; Serialization_enumKeyValue frequencyTypeValues[] = FREQUENCY_TYPE_ENUM_VALUES; call_virtual(writeEnumeration, context, "type", parameters.type, sizeof_count(frequencyTypeValues), frequencyTypeValues); switch (parameters.type) { case FREQUENCY_TYPE_FLAT: call_virtual(writeFloat, context, "base_value", parameters.info.flat.baseValue); break; case FREQUENCY_TYPE_RAMP: { call_virtual(writeFloat, context, "base_value", parameters.info.ramp.baseValue); call_virtual(writeFloat, context, "linear_ramp", parameters.info.ramp.linearRamp); call_virtual(writeFloat, context, "curved_ramp", parameters.info.ramp.curvedRamp); call_virtual(writeFloat, context, "onset", parameters.info.ramp.onset); call_virtual(writeFloat, context, "endpoint", parameters.info.ramp.endpoint); call_virtual(writeFloat, context, "reset_point", parameters.info.ramp.resetPoint); Serialization_enumKeyValue frequencyBoundTypeValues[] = FREQUENCY_BOUND_TYPE_ENUM_VALUES; call_virtual(writeEnumeration, context, "bound_type", parameters.info.ramp.boundType, sizeof_count(frequencyBoundTypeValues), frequencyBoundTypeValues); break; } case FREQUENCY_TYPE_STAIRSTEP: call_virtual(writeFloat, context, "base_value", parameters.info.stairstep.baseValue); call_virtual(beginArray, context, "steps"); for (unsigned int stepIndex = 0; stepIndex < parameters.info.stairstep.stepCount; stepIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeFloat, context, "duration", parameters.info.stairstep.steps[stepIndex].duration); call_virtual(writeFloat, context, "change", parameters.info.stairstep.steps[stepIndex].change); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(writeUInt16, context, "repeat_start_index", parameters.info.stairstep.repeatStartIndex); call_virtual(writeUInt16, context, "repeat_count", parameters.info.stairstep.repeatCount); break; case FREQUENCY_TYPE_SPLINE: call_virtual(beginStructure, context, "spline"); call_virtual(writeFloat, context, "base_value", parameters.info.spline.baseValue); writeSplineInfo(context, parameters.info.spline.spline); call_virtual(endStructure, context); break; case FREQUENCY_TYPE_VIBRATO: call_virtual(writeFloat, context, "base_value", parameters.info.vibrato.baseValue); call_virtual(writeFloat, context, "strength", parameters.info.vibrato.strength); call_virtual(writeFloat, context, "speed", parameters.info.vibrato.speed); call_virtual(writeFloat, context, "phase", parameters.info.vibrato.phase); break; case FREQUENCY_TYPE_LAYERED: { call_virtual(writeFloat, context, "base_value", parameters.info.layered.baseValue); Serialization_enumKeyValue blendModeValues[] = FREQUENCY_BLEND_MODE_ENUM_VALUES; call_virtual(writeEnumeration, context, "blend_mode", parameters.info.layered.blendMode, sizeof_count(blendModeValues), blendModeValues); call_virtual(beginArray, context, "layers"); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeFloat, context, "blend", parameters.info.layered.layers[layerIndex].blend); call_virtual(writeBoolean, context, "mute", parameters.info.layered.layers[layerIndex].mute); call_virtual(writeBoolean, context, "solo", parameters.info.layered.layers[layerIndex].solo); GeneralSynthConfiguration_serializeFrequencyParametersMinimal(parameters.info.layered.layers[layerIndex].parameters, context); call_virtual(endStructure, context); } call_virtual(endArray, context); break; } } } bool GeneralSynthConfiguration_deserializeFrequencyParameters(compat_type(DeserializationContext *) deserializationContext, struct GeneralSynthConfiguration_frequencyParameters * outParameters) { DeserializationContext * context = deserializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_frequency_formatType); const char * formatType = call_virtual(readString, context, "format_type"); if (formatType == NULL || strcmp(formatType, GeneralSynthConfiguration_frequency_formatType)) { return false; } uint16_t formatVersion = call_virtual(readUInt16, context, "format_version"); if (formatVersion > GeneralSynthConfiguration_frequency_formatVersion) { return false; } bool success = GeneralSynthConfiguration_deserializeFrequencyParametersMinimal(context, formatVersion, outParameters); call_virtual(endStructure, context); return success; } bool GeneralSynthConfiguration_deserializeFrequencyParametersMinimal(compat_type(DeserializationContext *) deserializationContext, uint16_t formatVersion, struct GeneralSynthConfiguration_frequencyParameters * outParameters) { DeserializationContext * context = deserializationContext; struct GeneralSynthConfiguration_frequencyParameters parameters; Serialization_enumKeyValue frequencyTypeValues[] = FREQUENCY_TYPE_ENUM_VALUES; parameters.type = call_virtual(readEnumeration, context, "type", sizeof_count(frequencyTypeValues), frequencyTypeValues); switch (parameters.type) { case FREQUENCY_TYPE_FLAT: parameters.info.flat.baseValue = call_virtual(readFloat, context, "base_value"); break; case FREQUENCY_TYPE_RAMP: { parameters.info.ramp.baseValue = call_virtual(readFloat, context, "base_value"); parameters.info.ramp.linearRamp = call_virtual(readFloat, context, "linear_ramp"); parameters.info.ramp.curvedRamp = call_virtual(readFloat, context, "curved_ramp"); parameters.info.ramp.onset = call_virtual(readFloat, context, "onset"); parameters.info.ramp.endpoint = call_virtual(readFloat, context, "endpoint"); parameters.info.ramp.resetPoint = call_virtual(readFloat, context, "reset_point"); Serialization_enumKeyValue frequencyBoundTypeValues[] = FREQUENCY_BOUND_TYPE_ENUM_VALUES; parameters.info.ramp.boundType = call_virtual(readEnumeration, context, "bound_type", sizeof_count(frequencyBoundTypeValues), frequencyBoundTypeValues); break; } case FREQUENCY_TYPE_STAIRSTEP: parameters.info.stairstep.baseValue = call_virtual(readFloat, context, "base_value"); parameters.info.stairstep.stepCount = call_virtual(beginArray, context, "steps"); parameters.info.stairstep.steps = malloc(parameters.info.stairstep.stepCount * sizeof(*parameters.info.stairstep.steps)); for (unsigned int stepIndex = 0; stepIndex < parameters.info.stairstep.stepCount; stepIndex++) { call_virtual(beginStructure, context, NULL); parameters.info.stairstep.steps[stepIndex].duration = call_virtual(readFloat, context, "duration"); parameters.info.stairstep.steps[stepIndex].change = call_virtual(readFloat, context, "change"); call_virtual(endStructure, context); } call_virtual(endArray, context); parameters.info.stairstep.repeatStartIndex = call_virtual(readUInt16, context, "repeat_start_index"); parameters.info.stairstep.repeatCount = call_virtual(readUInt16, context, "repeat_count"); break; case FREQUENCY_TYPE_SPLINE: call_virtual(beginStructure, context, "spline"); parameters.info.spline.baseValue = call_virtual(readFloat, context, "base_value"); parameters.info.spline.spline = readSplineInfo(context); call_virtual(endStructure, context); break; case FREQUENCY_TYPE_VIBRATO: parameters.info.vibrato.baseValue = call_virtual(readFloat, context, "base_value"); parameters.info.vibrato.strength = call_virtual(readFloat, context, "strength"); parameters.info.vibrato.speed = call_virtual(readFloat, context, "speed"); parameters.info.vibrato.phase = call_virtual(readFloat, context, "phase"); break; case FREQUENCY_TYPE_LAYERED: { parameters.info.layered.baseValue = call_virtual(readFloat, context, "base_value"); Serialization_enumKeyValue blendModeValues[] = FREQUENCY_BLEND_MODE_ENUM_VALUES; parameters.info.layered.blendMode = call_virtual(readEnumeration, context, "blend_mode", sizeof_count(blendModeValues), blendModeValues); parameters.info.layered.layerCount = call_virtual(beginArray, context, "layers"); parameters.info.layered.layers = calloc(parameters.info.layered.layerCount, sizeof(*parameters.info.layered.layers)); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { call_virtual(beginStructure, context, NULL); parameters.info.layered.layers[layerIndex].blend = call_virtual(readFloat, context, "blend"); parameters.info.layered.layers[layerIndex].mute = call_virtual(readBoolean, context, "mute"); parameters.info.layered.layers[layerIndex].solo = call_virtual(readBoolean, context, "solo"); GeneralSynthConfiguration_deserializeFrequencyParametersMinimal(context, formatVersion, ¶meters.info.layered.layers[layerIndex].parameters); call_virtual(endStructure, context); } call_virtual(endArray, context); break; } } if (context->status != SERIALIZATION_ERROR_OK) { GeneralSynthConfiguration_disposeFrequencyParameters(parameters); return false; } *outParameters = parameters; return true; } void GeneralSynthConfiguration_disposeFrequencyParameters(struct GeneralSynthConfiguration_frequencyParameters parameters) { switch (parameters.type) { case FREQUENCY_TYPE_FLAT: case FREQUENCY_TYPE_RAMP: case FREQUENCY_TYPE_VIBRATO: break; case FREQUENCY_TYPE_STAIRSTEP: free(parameters.info.stairstep.steps); break; case FREQUENCY_TYPE_SPLINE: disposeSplineInfo(¶meters.info.spline.spline); break; case FREQUENCY_TYPE_LAYERED: for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { GeneralSynthConfiguration_disposeFrequencyParameters(parameters.info.layered.layers[layerIndex].parameters); } free(parameters.info.layered.layers); break; } } GeneralSynthConfiguration_frequencyType getFrequencyType(FrequencyCurve * frequencyCurve) { if (StemObject_isExactClass(frequencyCurve, &FrequencyCurve_class)) { return FREQUENCY_TYPE_FLAT; } if (StemObject_isExactClass(frequencyCurve, &FrequencyCurve_stairstep_class)) { return FREQUENCY_TYPE_STAIRSTEP; } if (StemObject_isExactClass(frequencyCurve, &FrequencyCurve_ramp_class)) { return FREQUENCY_TYPE_RAMP; } if (StemObject_isExactClass(frequencyCurve, &FrequencyCurve_spline_class)) { return FREQUENCY_TYPE_SPLINE; } if (StemObject_isExactClass(frequencyCurve, &FrequencyCurve_vibrato_class)) { return FREQUENCY_TYPE_VIBRATO; } if (StemObject_isExactClass(frequencyCurve, &FrequencyCurve_layered_class)) { return FREQUENCY_TYPE_LAYERED; } #ifdef DEBUG fprintf(stderr, "Warning: Unknown frequency curve class %p passed to getFrequencyType\n", frequencyCurve->vtable); #endif return FREQUENCY_TYPE_FLAT; } const char * getFrequencyCurveHumanReadableName(GeneralSynthConfiguration_frequencyType type) { switch (type) { case FREQUENCY_TYPE_FLAT: return "Flat"; case FREQUENCY_TYPE_STAIRSTEP: return "Stairstep"; case FREQUENCY_TYPE_RAMP: return "Ramp"; case FREQUENCY_TYPE_SPLINE: return "Spline"; case FREQUENCY_TYPE_VIBRATO: return "Vibrato"; case FREQUENCY_TYPE_LAYERED: return "Layered"; } return "(unknown)"; } struct GeneralSynthConfiguration_waveParameters GeneralSynthConfiguration_createWaveParametersFromSampler(compat_type(WaveSampler *) waveSamplerUntyped) { WaveSampler * waveSampler = waveSamplerUntyped; struct GeneralSynthConfiguration_waveParameters parameters; parameters.type = getWaveType(waveSampler); switch (parameters.type) { case WAVE_TYPE_SINE: case WAVE_TYPE_TRIANGLE: case WAVE_TYPE_SPIKE: break; case WAVE_TYPE_PULSE: { WaveSampler_pulse * waveSamplerTyped = (WaveSampler_pulse *) waveSampler; parameters.info.pulse.duty = waveSamplerTyped->duty; parameters.info.pulse.amplitude = waveSamplerTyped->amplitude; break; } case WAVE_TYPE_SAWTOOTH: { WaveSampler_sawtooth * waveSamplerTyped = (WaveSampler_sawtooth *) waveSampler; parameters.info.sawtooth.incline = waveSamplerTyped->incline; parameters.info.sawtooth.amplitude = waveSamplerTyped->amplitude; break; } case WAVE_TYPE_WHITE_NOISE: { WaveSampler_noise * waveSamplerTyped = (WaveSampler_noise *) waveSampler; parameters.info.noise.seed = waveSamplerTyped->seed; parameters.info.noise.smooth = waveSamplerTyped->smoothSamples; break; } case WAVE_TYPE_PINK_NOISE: { WaveSampler_pinkNoise * waveSamplerTyped = (WaveSampler_pinkNoise *) waveSampler; parameters.info.noise.seed = waveSamplerTyped->seed; parameters.info.noise.smooth = waveSamplerTyped->smoothSamples; break; } case WAVE_TYPE_BITNOISE: { WaveSampler_bitnoise * waveSamplerTyped = (WaveSampler_bitnoise *) waveSampler; parameters.info.noise.seed = waveSamplerTyped->seed; break; } case WAVE_TYPE_SPLINE: { WaveSampler_spline * waveSamplerTyped = (WaveSampler_spline *) waveSampler; parameters.info.spline.spline = copySplineInfo(&waveSamplerTyped->spline); break; } case WAVE_TYPE_PCM_DATA: { WaveSampler_pcmData * waveSamplerTyped = (WaveSampler_pcmData *) waveSampler; parameters.info.pcmData.audioData = PCMAudio_copy(waveSamplerTyped->audioData); parameters.info.pcmData.loop = waveSamplerTyped->loop; parameters.info.pcmData.startFrameIndex = waveSamplerTyped->startFrameIndex; parameters.info.pcmData.frameCount = waveSamplerTyped->frameCount; break; } case WAVE_TYPE_LAYERED: { WaveSampler_layered * waveSamplerTyped = (WaveSampler_layered *) waveSampler; parameters.info.layered.blendMode = waveSamplerTyped->blendMode; parameters.info.layered.layerCount = waveSamplerTyped->layerCount; parameters.info.layered.layers = calloc(parameters.info.layered.layerCount, sizeof(*parameters.info.layered.layers)); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { parameters.info.layered.layers[layerIndex].blend = waveSamplerTyped->layers[layerIndex].blend; parameters.info.layered.layers[layerIndex].mute = waveSamplerTyped->layers[layerIndex].mute; parameters.info.layered.layers[layerIndex].solo = waveSamplerTyped->layers[layerIndex].solo; parameters.info.layered.layers[layerIndex].frequencyOffset = waveSamplerTyped->layers[layerIndex].frequencyOffset; parameters.info.layered.layers[layerIndex].phaseOffset = waveSamplerTyped->layers[layerIndex].phaseOffset; parameters.info.layered.layers[layerIndex].parameters = GeneralSynthConfiguration_createWaveParametersFromSampler(waveSamplerTyped->layers[layerIndex].sampler); } break; } case WAVE_TYPE_MODIFIED: { WaveSampler_modified * waveSamplerTyped = (WaveSampler_modified *) waveSampler; parameters.info.modified.samplerParameters = malloc(sizeof(*parameters.info.modified.samplerParameters)); *parameters.info.modified.samplerParameters = GeneralSynthConfiguration_createWaveParametersFromSampler(waveSamplerTyped->sampler); parameters.info.modified.modifierCount = waveSamplerTyped->modifierCount; parameters.info.modified.modifiers = calloc(parameters.info.modified.modifierCount, sizeof(*parameters.info.modified.modifiers)); for (unsigned int modifierIndex = 0; modifierIndex < parameters.info.modified.modifierCount; modifierIndex++) { parameters.info.modified.modifiers[modifierIndex] = GeneralSynthConfiguration_createWaveModifierParametersFromModifier(waveSamplerTyped->modifiers[modifierIndex]); } break; } } return parameters; } WaveSampler * GeneralSynthConfiguration_createWaveSamplerFromParameters(struct GeneralSynthConfiguration_waveParameters parameters) { switch (parameters.type) { case WAVE_TYPE_SINE: return (WaveSampler *) WaveSampler_sine_create(); case WAVE_TYPE_PULSE: return (WaveSampler *) WaveSampler_pulse_create(parameters.info.pulse.duty, parameters.info.pulse.amplitude); case WAVE_TYPE_SAWTOOTH: return (WaveSampler *) WaveSampler_sawtooth_create(parameters.info.sawtooth.incline, parameters.info.sawtooth.amplitude); case WAVE_TYPE_TRIANGLE: return (WaveSampler *) WaveSampler_triangle_create(); case WAVE_TYPE_WHITE_NOISE: return (WaveSampler *) WaveSampler_noise_create(parameters.info.noise.seed, parameters.info.noise.smooth); case WAVE_TYPE_PINK_NOISE: return (WaveSampler *) WaveSampler_pinkNoise_create(parameters.info.noise.seed, parameters.info.noise.smooth); case WAVE_TYPE_BITNOISE: return (WaveSampler *) WaveSampler_bitnoise_create(parameters.info.noise.seed); case WAVE_TYPE_SPIKE: return (WaveSampler *) WaveSampler_spike_create(); case WAVE_TYPE_SPLINE: return (WaveSampler *) WaveSampler_spline_create(copySplineInfo(¶meters.info.spline.spline)); case WAVE_TYPE_PCM_DATA: return (WaveSampler *) WaveSampler_pcmData_create(parameters.info.pcmData.audioData, parameters.info.pcmData.loop, parameters.info.pcmData.startFrameIndex, parameters.info.pcmData.frameCount); case WAVE_TYPE_LAYERED: { struct WaveSampler_layered_layer layers[parameters.info.layered.layerCount]; for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { layers[layerIndex].blend = parameters.info.layered.layers[layerIndex].blend; layers[layerIndex].mute = parameters.info.layered.layers[layerIndex].mute; layers[layerIndex].solo = parameters.info.layered.layers[layerIndex].solo; layers[layerIndex].frequencyOffset = parameters.info.layered.layers[layerIndex].frequencyOffset; layers[layerIndex].phaseOffset = parameters.info.layered.layers[layerIndex].phaseOffset; layers[layerIndex].sampler = GeneralSynthConfiguration_createWaveSamplerFromParameters(parameters.info.layered.layers[layerIndex].parameters); } return (WaveSampler *) WaveSampler_layered_create(parameters.info.layered.blendMode, parameters.info.layered.layerCount, layers); } case WAVE_TYPE_MODIFIED: { WaveModifier * modifiers[parameters.info.modified.modifierCount]; for (unsigned int modifierIndex = 0; modifierIndex < parameters.info.modified.modifierCount; modifierIndex++) { modifiers[modifierIndex] = GeneralSynthConfiguration_createWaveModifierFromParameters(parameters.info.modified.modifiers[modifierIndex]); } return (WaveSampler *) WaveSampler_modified_create(GeneralSynthConfiguration_createWaveSamplerFromParameters(*parameters.info.modified.samplerParameters), parameters.info.modified.modifierCount, modifiers); } } return NULL; } void GeneralSynthConfiguration_serializeWaveParameters(struct GeneralSynthConfiguration_waveParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_wave_formatType); call_virtual(writeString, context, "format_type", GeneralSynthConfiguration_wave_formatType); call_virtual(writeUInt16, context, "format_version", GeneralSynthConfiguration_wave_formatVersion); GeneralSynthConfiguration_serializeWaveParametersMinimal(parameters, context); call_virtual(endStructure, context); } #define WAVE_TYPE_ENUM_VALUES { \ {"sine", WAVE_TYPE_SINE}, \ {"pulse", WAVE_TYPE_PULSE}, \ {"sawtooth", WAVE_TYPE_SAWTOOTH}, \ {"triangle", WAVE_TYPE_TRIANGLE}, \ {"noise", WAVE_TYPE_WHITE_NOISE}, \ {"pink", WAVE_TYPE_PINK_NOISE}, \ {"bitnoise", WAVE_TYPE_BITNOISE}, \ {"spike", WAVE_TYPE_SPIKE}, \ {"spline", WAVE_TYPE_SPLINE}, \ {"pcm", WAVE_TYPE_PCM_DATA}, \ {"layered", WAVE_TYPE_LAYERED}, \ {"modified", WAVE_TYPE_MODIFIED} \ } #define WAVE_BLEND_MODE_ENUM_VALUES { \ {"add", WaveSampler_layered_add}, \ {"multiply", WaveSampler_layered_multiply}, \ {"average", WaveSampler_layered_average} \ } void GeneralSynthConfiguration_serializeWaveParametersMinimal(struct GeneralSynthConfiguration_waveParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; Serialization_enumKeyValue waveTypeValues[] = WAVE_TYPE_ENUM_VALUES; call_virtual(writeEnumeration, context, "type", parameters.type, sizeof_count(waveTypeValues), waveTypeValues); switch (parameters.type) { case WAVE_TYPE_SINE: case WAVE_TYPE_TRIANGLE: case WAVE_TYPE_SPIKE: break; case WAVE_TYPE_PULSE: call_virtual(writeFloat, context, "duty", parameters.info.pulse.duty); call_virtual(writeFloat, context, "amplitude", parameters.info.pulse.amplitude); break; case WAVE_TYPE_SAWTOOTH: call_virtual(writeFloat, context, "incline", parameters.info.sawtooth.incline); call_virtual(writeFloat, context, "amplitude", parameters.info.sawtooth.amplitude); break; case WAVE_TYPE_WHITE_NOISE: case WAVE_TYPE_PINK_NOISE: call_virtual(writeUInt32, context, "seed", parameters.info.noise.seed); call_virtual(writeBoolean, context, "smooth", parameters.info.noise.smooth); break; case WAVE_TYPE_BITNOISE: call_virtual(writeUInt32, context, "seed", parameters.info.noise.seed); break; case WAVE_TYPE_SPLINE: call_virtual(beginStructure, context, "spline"); writeSplineInfo(context, parameters.info.spline.spline); call_virtual(endStructure, context); break; case WAVE_TYPE_PCM_DATA: call_virtual(writeUInt8, context, "bytes_per_sample", parameters.info.pcmData.audioData->bytesPerSample); call_virtual(writeUInt8, context, "channel_count", parameters.info.pcmData.audioData->channelCount); call_virtual(writeUInt32, context, "sample_rate", parameters.info.pcmData.audioData->sampleRate); call_virtual(writeBlob, context, "data", parameters.info.pcmData.audioData->samples, parameters.info.pcmData.audioData->frameCount * parameters.info.pcmData.audioData->bytesPerSample); call_virtual(writeBoolean, context, "loop", parameters.info.pcmData.loop); call_virtual(writeUInt32, context, "offset", parameters.info.pcmData.startFrameIndex); call_virtual(writeUInt32, context, "length", parameters.info.pcmData.frameCount); break; case WAVE_TYPE_LAYERED: { Serialization_enumKeyValue waveBlendTypeValues[] = WAVE_BLEND_MODE_ENUM_VALUES; call_virtual(writeEnumeration, context, "blend_mode", parameters.info.layered.blendMode, sizeof_count(waveBlendTypeValues), waveBlendTypeValues); call_virtual(beginArray, context, "layers"); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeFloat, context, "blend", parameters.info.layered.layers[layerIndex].blend); call_virtual(writeBoolean, context, "mute", parameters.info.layered.layers[layerIndex].mute); call_virtual(writeBoolean, context, "solo", parameters.info.layered.layers[layerIndex].solo); call_virtual(writeFloat, context, "frequency_offset", parameters.info.layered.layers[layerIndex].frequencyOffset); call_virtual(writeFloat, context, "phase_offset", parameters.info.layered.layers[layerIndex].phaseOffset); GeneralSynthConfiguration_serializeWaveParametersMinimal(parameters.info.layered.layers[layerIndex].parameters, context); call_virtual(endStructure, context); } call_virtual(endArray, context); break; } case WAVE_TYPE_MODIFIED: call_virtual(beginStructure, context, "sampler"); GeneralSynthConfiguration_serializeWaveParametersMinimal(*parameters.info.modified.samplerParameters, serializationContext); call_virtual(endStructure, context); call_virtual(beginArray, context, "modifiers"); for (unsigned int modifierIndex = 0; modifierIndex < parameters.info.modified.modifierCount; modifierIndex++) { call_virtual(beginStructure, context, NULL); GeneralSynthConfiguration_serializeWaveModifierParametersMinimal(parameters.info.modified.modifiers[modifierIndex], context); call_virtual(endStructure, context); } call_virtual(endArray, context); break; } } bool GeneralSynthConfiguration_deserializeWaveParameters(compat_type(DeserializationContext *) deserializationContext, struct GeneralSynthConfiguration_waveParameters * outParameters) { DeserializationContext * context = deserializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_wave_formatType); const char * formatType = call_virtual(readString, context, "format_type"); if (formatType == NULL || strcmp(formatType, GeneralSynthConfiguration_wave_formatType)) { return false; } uint16_t formatVersion = call_virtual(readUInt16, context, "format_version"); if (formatVersion > GeneralSynthConfiguration_wave_formatVersion) { return false; } bool success = GeneralSynthConfiguration_deserializeWaveParametersMinimal(context, formatVersion, outParameters); call_virtual(endStructure, context); return success; } bool GeneralSynthConfiguration_deserializeWaveParametersMinimal(compat_type(DeserializationContext *) deserializationContext, uint16_t formatVersion, struct GeneralSynthConfiguration_waveParameters * outParameters) { DeserializationContext * context = deserializationContext; struct GeneralSynthConfiguration_waveParameters parameters; Serialization_enumKeyValue waveTypeValues[] = WAVE_TYPE_ENUM_VALUES; parameters.type = call_virtual(readEnumeration, context, "type", sizeof_count(waveTypeValues), waveTypeValues); switch (parameters.type) { case WAVE_TYPE_SINE: case WAVE_TYPE_TRIANGLE: case WAVE_TYPE_SPIKE: break; case WAVE_TYPE_PULSE: parameters.info.pulse.duty = call_virtual(readFloat, context, "duty"); parameters.info.pulse.amplitude = call_virtual(readFloat, context, "amplitude"); break; case WAVE_TYPE_SAWTOOTH: parameters.info.sawtooth.incline = call_virtual(readFloat, context, "incline"); parameters.info.sawtooth.amplitude = call_virtual(readFloat, context, "amplitude"); break; case WAVE_TYPE_WHITE_NOISE: case WAVE_TYPE_PINK_NOISE: parameters.info.noise.seed = call_virtual(readUInt32, context, "seed"); parameters.info.noise.smooth = call_virtual(readBoolean, context, "smooth"); break; case WAVE_TYPE_BITNOISE: parameters.info.noise.seed = call_virtual(readUInt32, context, "seed"); break; case WAVE_TYPE_SPLINE: call_virtual(beginStructure, context, "spline"); parameters.info.spline.spline = readSplineInfo(context); call_virtual(endStructure, context); break; case WAVE_TYPE_PCM_DATA: { size_t dataLength; unsigned int bytesPerSample = call_virtual(readUInt8, context, "bytes_per_sample"); unsigned int channelCount = call_virtual(readUInt8, context, "channel_count"); unsigned int sampleRate = call_virtual(readUInt32, context, "sample_rate"); const void * samples = call_virtual(readBlob, context, "data", &dataLength); parameters.info.pcmData.audioData = PCMAudio_create(bytesPerSample, channelCount, sampleRate, dataLength / bytesPerSample, (void *) samples, true); parameters.info.pcmData.loop = call_virtual(readBoolean, context, "loop"); parameters.info.pcmData.startFrameIndex = call_virtual(readUInt32, context, "offset"); parameters.info.pcmData.frameCount = call_virtual(readUInt32, context, "length"); break; } case WAVE_TYPE_LAYERED: { Serialization_enumKeyValue waveBlendModeValues[] = WAVE_BLEND_MODE_ENUM_VALUES; parameters.info.layered.blendMode = call_virtual(readEnumeration, context, "blend_mode", sizeof_count(waveBlendModeValues), waveBlendModeValues); parameters.info.layered.layerCount = call_virtual(beginArray, context, "layers"); parameters.info.layered.layers = calloc(parameters.info.layered.layerCount, sizeof(*parameters.info.layered.layers)); for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { call_virtual(beginStructure, context, NULL); parameters.info.layered.layers[layerIndex].blend = call_virtual(readFloat, context, "blend"); parameters.info.layered.layers[layerIndex].mute = call_virtual(readBoolean, context, "mute"); parameters.info.layered.layers[layerIndex].solo = call_virtual(readBoolean, context, "solo"); parameters.info.layered.layers[layerIndex].frequencyOffset = call_virtual(readFloat, context, "frequency_offset"); parameters.info.layered.layers[layerIndex].phaseOffset = call_virtual(readFloat, context, "phase_offset"); GeneralSynthConfiguration_deserializeWaveParametersMinimal(context, formatVersion, ¶meters.info.layered.layers[layerIndex].parameters); call_virtual(endStructure, context); } call_virtual(endArray, context); break; } case WAVE_TYPE_MODIFIED: call_virtual(beginStructure, context, "sampler"); parameters.info.modified.samplerParameters = malloc(sizeof(*parameters.info.modified.samplerParameters)); GeneralSynthConfiguration_deserializeWaveParametersMinimal(context, formatVersion, parameters.info.modified.samplerParameters); call_virtual(endStructure, context); parameters.info.modified.modifierCount = call_virtual(beginArray, context, "modifiers"); parameters.info.modified.modifiers = calloc(parameters.info.modified.modifierCount, sizeof(*parameters.info.modified.modifiers)); for (unsigned int modifierIndex = 0; modifierIndex < parameters.info.modified.modifierCount; modifierIndex++) { call_virtual(beginStructure, context, NULL); GeneralSynthConfiguration_deserializeWaveModifierParametersMinimal(context, 0, ¶meters.info.modified.modifiers[modifierIndex]); call_virtual(endStructure, context); } call_virtual(endArray, context); break; } if (context->status != SERIALIZATION_ERROR_OK) { GeneralSynthConfiguration_disposeWaveParameters(parameters); return false; } *outParameters = parameters; return true; } void GeneralSynthConfiguration_disposeWaveParameters(struct GeneralSynthConfiguration_waveParameters parameters) { switch (parameters.type) { case WAVE_TYPE_SINE: case WAVE_TYPE_PULSE: case WAVE_TYPE_SAWTOOTH: case WAVE_TYPE_TRIANGLE: case WAVE_TYPE_WHITE_NOISE: case WAVE_TYPE_PINK_NOISE: case WAVE_TYPE_BITNOISE: case WAVE_TYPE_SPIKE: break; case WAVE_TYPE_SPLINE: disposeSplineInfo(¶meters.info.spline.spline); break; case WAVE_TYPE_PCM_DATA: PCMAudio_dispose(parameters.info.pcmData.audioData); break; case WAVE_TYPE_LAYERED: for (unsigned int layerIndex = 0; layerIndex < parameters.info.layered.layerCount; layerIndex++) { GeneralSynthConfiguration_disposeWaveParameters(parameters.info.layered.layers[layerIndex].parameters); } free(parameters.info.layered.layers); break; case WAVE_TYPE_MODIFIED: GeneralSynthConfiguration_disposeWaveParameters(*parameters.info.modified.samplerParameters); free(parameters.info.modified.samplerParameters); for (unsigned int modifierIndex = 0; modifierIndex < parameters.info.modified.modifierCount; modifierIndex++) { GeneralSynthConfiguration_disposeWaveModifierParameters(parameters.info.modified.modifiers[modifierIndex]); } free(parameters.info.modified.modifiers); break; } } GeneralSynthConfiguration_waveType getWaveType(WaveSampler * waveSampler) { if (StemObject_isExactClass(waveSampler, &WaveSampler_sine_class)) { return WAVE_TYPE_SINE; } if (StemObject_isExactClass(waveSampler, &WaveSampler_pulse_class)) { return WAVE_TYPE_PULSE; } if (StemObject_isExactClass(waveSampler, &WaveSampler_sawtooth_class)) { return WAVE_TYPE_SAWTOOTH; } if (StemObject_isExactClass(waveSampler, &WaveSampler_triangle_class)) { return WAVE_TYPE_TRIANGLE; } if (StemObject_isExactClass(waveSampler, &WaveSampler_noise_class)) { return WAVE_TYPE_WHITE_NOISE; } if (StemObject_isExactClass(waveSampler, &WaveSampler_pinkNoise_class)) { return WAVE_TYPE_PINK_NOISE; } if (StemObject_isExactClass(waveSampler, &WaveSampler_bitnoise_class)) { return WAVE_TYPE_BITNOISE; } if (StemObject_isExactClass(waveSampler, &WaveSampler_spike_class)) { return WAVE_TYPE_SPIKE; } if (StemObject_isExactClass(waveSampler, &WaveSampler_spline_class)) { return WAVE_TYPE_SPLINE; } if (StemObject_isExactClass(waveSampler, &WaveSampler_pcmData_class)) { return WAVE_TYPE_PCM_DATA; } if (StemObject_isExactClass(waveSampler, &WaveSampler_layered_class)) { return WAVE_TYPE_LAYERED; } if (StemObject_isExactClass(waveSampler, &WaveSampler_modified_class)) { return WAVE_TYPE_MODIFIED; } #ifdef DEBUG fprintf(stderr, "Warning: Unknown wave shape class %p passed to getWaveType\n", waveSampler->vtable); #endif return WAVE_TYPE_SINE; } const char * getWaveSamplerHumanReadableName(GeneralSynthConfiguration_waveType type) { switch (type) { case WAVE_TYPE_SINE: return "Sine"; case WAVE_TYPE_PULSE: return "Pulse"; case WAVE_TYPE_SAWTOOTH: return "Sawtooth"; case WAVE_TYPE_TRIANGLE: return "Triangle"; case WAVE_TYPE_WHITE_NOISE: return "White noise"; case WAVE_TYPE_PINK_NOISE: return "Pink noise"; case WAVE_TYPE_BITNOISE: return "Bitnoise"; case WAVE_TYPE_SPIKE: return "Spike"; case WAVE_TYPE_SPLINE: return "Spline"; case WAVE_TYPE_PCM_DATA: return "PCM data"; case WAVE_TYPE_LAYERED: return "Layered"; case WAVE_TYPE_MODIFIED: return "Modified"; } return "(unknown)"; } struct GeneralSynthConfiguration_signalFilterParameters GeneralSynthConfiguration_createSignalFilterParametersFromFilter(compat_type(SignalFilter *) signalFilterUntyped) { SignalFilter * signalFilter = signalFilterUntyped; struct GeneralSynthConfiguration_signalFilterParameters parameters; parameters.type = getSignalFilterType(signalFilter); switch (parameters.type) { case SIGNAL_FILTER_TYPE_BITCRUSH: parameters.info.bitcrush.numericResolution = ((SignalFilter_bitcrush *) signalFilter)->numericResolution; parameters.info.bitcrush.temporalResolution = ((SignalFilter_bitcrush *) signalFilter)->temporalResolution; break; case SIGNAL_FILTER_TYPE_COMPRESSION: parameters.info.compression.strength = ((SignalFilter_compression *) signalFilter)->strength; break; case SIGNAL_FILTER_TYPE_DISTORTION: parameters.info.distortion.amplification = ((SignalFilter_distortion *) signalFilter)->amplification; parameters.info.distortion.clipRange = ((SignalFilter_distortion *) signalFilter)->clipRange; break; case SIGNAL_FILTER_TYPE_DELAY: parameters.info.delay.interval = ((SignalFilter_delay *) signalFilter)->interval; parameters.info.delay.falloff = ((SignalFilter_delay *) signalFilter)->falloff; parameters.info.delay.repeatCount = ((SignalFilter_delay *) signalFilter)->repeatCount; break; } parameters.name = strdup(signalFilter->name); parameters.blend = signalFilter->blend; parameters.mute = signalFilter->mute; parameters.solo = signalFilter->solo; return parameters; } SignalFilter * GeneralSynthConfiguration_createSignalFilterFromParameters(struct GeneralSynthConfiguration_signalFilterParameters parameters) { SignalFilter * filter = NULL; switch (parameters.type) { case SIGNAL_FILTER_TYPE_BITCRUSH: filter = (SignalFilter *) SignalFilter_bitcrush_create(parameters.info.bitcrush.numericResolution, parameters.info.bitcrush.temporalResolution); break; case SIGNAL_FILTER_TYPE_COMPRESSION: filter = (SignalFilter *) SignalFilter_compression_create(parameters.info.compression.strength); break; case SIGNAL_FILTER_TYPE_DISTORTION: filter = (SignalFilter *) SignalFilter_distortion_create(parameters.info.distortion.amplification, parameters.info.distortion.clipRange); break; case SIGNAL_FILTER_TYPE_DELAY: filter = (SignalFilter *) SignalFilter_delay_create(parameters.info.delay.interval, parameters.info.delay.falloff, parameters.info.delay.repeatCount); break; } if (filter != NULL) { filter->name = strdup(parameters.name); filter->blend = parameters.blend; filter->mute = parameters.mute; filter->solo = parameters.solo; } return filter; } void GeneralSynthConfiguration_serializeSignalFilterParameters(struct GeneralSynthConfiguration_signalFilterParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_signalFilter_formatType); call_virtual(writeString, context, "format_type", GeneralSynthConfiguration_signalFilter_formatType); call_virtual(writeUInt16, context, "format_version", GeneralSynthConfiguration_signalFilter_formatVersion); GeneralSynthConfiguration_serializeSignalFilterParametersMinimal(parameters, context); call_virtual(endStructure, context); } #define SIGNAL_FILTER_TYPE_ENUM_VALUES { \ {"bitcrush", SIGNAL_FILTER_TYPE_BITCRUSH}, \ {"compression", SIGNAL_FILTER_TYPE_COMPRESSION}, \ {"distortion", SIGNAL_FILTER_TYPE_DISTORTION}, \ {"delay", SIGNAL_FILTER_TYPE_DELAY} \ } void GeneralSynthConfiguration_serializeSignalFilterParametersMinimal(struct GeneralSynthConfiguration_signalFilterParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(writeString, context, "name", parameters.name); call_virtual(writeFloat, context, "blend", parameters.blend); call_virtual(writeBoolean, context, "mute", parameters.mute); call_virtual(writeBoolean, context, "solo", parameters.solo); Serialization_enumKeyValue signalFilterTypeValues[] = SIGNAL_FILTER_TYPE_ENUM_VALUES; call_virtual(writeEnumeration, context, "type", parameters.type, sizeof_count(signalFilterTypeValues), signalFilterTypeValues); switch (parameters.type) { case SIGNAL_FILTER_TYPE_BITCRUSH: call_virtual(writeFloat, context, "numeric_resolution", parameters.info.bitcrush.numericResolution); call_virtual(writeFloat, context, "temporal_resolution", parameters.info.bitcrush.temporalResolution); break; case SIGNAL_FILTER_TYPE_COMPRESSION: call_virtual(writeFloat, context, "strength", parameters.info.compression.strength); break; case SIGNAL_FILTER_TYPE_DISTORTION: call_virtual(writeFloat, context, "amplification", parameters.info.distortion.amplification); call_virtual(writeFloat, context, "clip_range", parameters.info.distortion.clipRange); break; case SIGNAL_FILTER_TYPE_DELAY: call_virtual(writeFloat, context, "interval", parameters.info.delay.interval); call_virtual(writeFloat, context, "falloff", parameters.info.delay.falloff); call_virtual(writeUInt8, context, "repeat_count", parameters.info.delay.repeatCount); break; } } bool GeneralSynthConfiguration_deserializeSignalFilterParameters(compat_type(DeserializationContext *) deserializationContext, struct GeneralSynthConfiguration_signalFilterParameters * outParameters) { DeserializationContext * context = deserializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_signalFilter_formatType); const char * formatType = call_virtual(readString, context, "format_type"); if (formatType == NULL || strcmp(formatType, GeneralSynthConfiguration_signalFilter_formatType)) { return false; } uint16_t formatVersion = call_virtual(readUInt16, context, "format_version"); if (formatVersion > GeneralSynthConfiguration_signalFilter_formatVersion) { return false; } bool success = GeneralSynthConfiguration_deserializeSignalFilterParametersMinimal(context, formatVersion, outParameters); call_virtual(endStructure, context); return success; } bool GeneralSynthConfiguration_deserializeSignalFilterParametersMinimal(compat_type(DeserializationContext *) deserializationContext, uint16_t formatVersion, struct GeneralSynthConfiguration_signalFilterParameters * outParameters) { DeserializationContext * context = deserializationContext; struct GeneralSynthConfiguration_signalFilterParameters parameters; parameters.name = strdup_nullSafe(call_virtual(readString, context, "name")); parameters.blend = call_virtual(readFloat, context, "blend"); parameters.mute = call_virtual(readBoolean, context, "mute"); parameters.solo = call_virtual(readBoolean, context, "solo"); Serialization_enumKeyValue signalFilterTypeValues[] = SIGNAL_FILTER_TYPE_ENUM_VALUES; parameters.type = call_virtual(readEnumeration, context, "type", sizeof_count(signalFilterTypeValues), signalFilterTypeValues); switch (parameters.type) { case SIGNAL_FILTER_TYPE_BITCRUSH: parameters.info.bitcrush.numericResolution = call_virtual(readFloat, context, "numeric_resolution"); parameters.info.bitcrush.temporalResolution = call_virtual(readFloat, context, "temporal_resolution"); break; case SIGNAL_FILTER_TYPE_COMPRESSION: parameters.info.compression.strength = call_virtual(readFloat, context, "strength"); break; case SIGNAL_FILTER_TYPE_DISTORTION: parameters.info.distortion.amplification = call_virtual(readFloat, context, "amplification"); parameters.info.distortion.clipRange = call_virtual(readFloat, context, "clip_range"); break; case SIGNAL_FILTER_TYPE_DELAY: parameters.info.delay.interval = call_virtual(readFloat, context, "interval"); parameters.info.delay.falloff = call_virtual(readFloat, context, "falloff"); parameters.info.delay.repeatCount = call_virtual(readUInt8, context, "repeat_count"); break; } if (context->status != SERIALIZATION_ERROR_OK) { GeneralSynthConfiguration_disposeSignalFilterParameters(parameters); return false; } *outParameters = parameters; return true; } void GeneralSynthConfiguration_disposeSignalFilterParameters(struct GeneralSynthConfiguration_signalFilterParameters parameters) { switch (parameters.type) { case SIGNAL_FILTER_TYPE_BITCRUSH: case SIGNAL_FILTER_TYPE_COMPRESSION: case SIGNAL_FILTER_TYPE_DISTORTION: case SIGNAL_FILTER_TYPE_DELAY: break; } free(parameters.name); } GeneralSynthConfiguration_signalFilterType getSignalFilterType(SignalFilter * signalFilter) { if (StemObject_isExactClass(signalFilter, &SignalFilter_bitcrush_class)) { return SIGNAL_FILTER_TYPE_BITCRUSH; } if (StemObject_isExactClass(signalFilter, &SignalFilter_compression_class)) { return SIGNAL_FILTER_TYPE_COMPRESSION; } if (StemObject_isExactClass(signalFilter, &SignalFilter_distortion_class)) { return SIGNAL_FILTER_TYPE_DISTORTION; } if (StemObject_isExactClass(signalFilter, &SignalFilter_delay_class)) { return SIGNAL_FILTER_TYPE_DELAY; } #ifdef DEBUG fprintf(stderr, "Warning: Unknown signal filter class %p passed to getSignalFilterType\n", signalFilter->vtable); #endif return SIGNAL_FILTER_TYPE_DISTORTION; } const char * getSignalFilterHumanReadableName(GeneralSynthConfiguration_signalFilterType type) { switch (type) { case SIGNAL_FILTER_TYPE_BITCRUSH: return "Bitcrush"; case SIGNAL_FILTER_TYPE_COMPRESSION: return "Compression"; case SIGNAL_FILTER_TYPE_DISTORTION: return "Distortion"; case SIGNAL_FILTER_TYPE_DELAY: return "Delay"; } return "(unknown)"; } struct GeneralSynthConfiguration_waveModifierParameters GeneralSynthConfiguration_createWaveModifierParametersFromModifier(compat_type(WaveModifier *) waveModifier) { struct GeneralSynthConfiguration_waveModifierParameters parameters; parameters.type = getWaveModifierType(waveModifier); parameters.blend = ((WaveModifier *) waveModifier)->blend; parameters.mute = ((WaveModifier *) waveModifier)->mute; parameters.solo = ((WaveModifier *) waveModifier)->solo; switch (parameters.type) { case WAVE_MODIFIER_TYPE_DISTORTION: { WaveModifier_distortion * waveModifierTyped = waveModifier; parameters.info.distortion.amplification = waveModifierTyped->amplification; parameters.info.distortion.clipRange = waveModifierTyped->clipRange; break; } case WAVE_MODIFIER_TYPE_HARMONICS: { WaveModifier_harmonics * waveModifierTyped = waveModifier; parameters.info.harmonics.toneCount = waveModifierTyped->toneCount; parameters.info.harmonics.frequencySpacing = waveModifierTyped->frequencySpacing; parameters.info.harmonics.falloff = waveModifierTyped->falloff; parameters.info.harmonics.averageAmplitude = waveModifierTyped->averageAmplitude; break; } case WAVE_MODIFIER_TYPE_RESET: { WaveModifier_reset * waveModifierTyped = waveModifier; parameters.info.reset.resetPoint = waveModifierTyped->resetPoint; break; } case WAVE_MODIFIER_TYPE_SUPERSAMPLE: { WaveModifier_supersample * waveModifierTyped = waveModifier; parameters.info.supersample.sampleCount = waveModifierTyped->sampleCount; break; } case WAVE_MODIFIER_TYPE_CHORD: { WaveModifier_chord * waveModifierTyped = waveModifier; parameters.info.chord.noteCount = waveModifierTyped->noteCount; parameters.info.chord.notes = memdup(waveModifierTyped->notes, waveModifierTyped->noteCount * sizeof(*waveModifierTyped->notes)); break; } case WAVE_MODIFIER_TYPE_PHASER: { WaveModifier_phaser * waveModifierTyped = waveModifier; parameters.info.phaser.timeOffset = waveModifierTyped->timeOffset; parameters.info.phaser.smooth = waveModifierTyped->smooth; parameters.info.phaser.bufferSize = waveModifierTyped->bufferSize; break; } case WAVE_MODIFIER_TYPE_SFXRHIGHLOWPASS: { WaveModifier_sfxrHighLowpass * waveModifierTyped = waveModifier; parameters.info.sfxrHighLowpass.lpCutoff = waveModifierTyped->lpCutoff; parameters.info.sfxrHighLowpass.lpRamp = waveModifierTyped->lpRamp; parameters.info.sfxrHighLowpass.lpResonance = waveModifierTyped->lpResonance; parameters.info.sfxrHighLowpass.hpCutoff = waveModifierTyped->hpCutoff; parameters.info.sfxrHighLowpass.hpRamp = waveModifierTyped->hpRamp; break; } case WAVE_MODIFIER_TYPE_HIGHLOWPASS: { WaveModifier_highLowpass * waveModifierTyped = waveModifier; parameters.info.highLowpass.lpStrength = waveModifierTyped->lpStrength; parameters.info.highLowpass.hpStrength = waveModifierTyped->hpStrength; break; } case WAVE_MODIFIER_TYPE_TIME_VALUE_TRANSFORM: { WaveModifier_timeValueTransform * waveModifierTyped = waveModifier; parameters.info.timeValueTransform.timeOffset = waveModifierTyped->timeOffset; parameters.info.timeValueTransform.timeScale = waveModifierTyped->timeScale; parameters.info.timeValueTransform.valueOffset = waveModifierTyped->valueOffset; parameters.info.timeValueTransform.valueScale = waveModifierTyped->valueScale; break; } case WAVE_MODIFIER_TYPE_THINNING: { WaveModifier_thinning * waveModifierTyped = waveModifier; parameters.info.thinning.amount = waveModifierTyped->amount; parameters.info.thinning.center = waveModifierTyped->center; break; } case WAVE_MODIFIER_TYPE_TIME_CURVE: { WaveModifier_timeCurve * waveModifierTyped = waveModifier; parameters.info.timeCurve.strength = waveModifierTyped->strength; parameters.info.timeCurve.center = waveModifierTyped->center; break; } case WAVE_MODIFIER_TYPE_RING_MODULATION: { WaveModifier_ringModulation * waveModifierTyped = waveModifier; parameters.info.ringModulation.carrierFrequency = waveModifierTyped->carrierFrequency; parameters.info.ringModulation.carrierPhaseOffset = waveModifierTyped->carrierPhaseOffset; parameters.info.ringModulation.carrierParameters = malloc(sizeof(*parameters.info.ringModulation.carrierParameters)); *parameters.info.ringModulation.carrierParameters = GeneralSynthConfiguration_createWaveParametersFromSampler(waveModifierTyped->carrier); break; } } return parameters; } WaveModifier * GeneralSynthConfiguration_createWaveModifierFromParameters(struct GeneralSynthConfiguration_waveModifierParameters parameters) { WaveModifier * result = NULL; switch (parameters.type) { case WAVE_MODIFIER_TYPE_DISTORTION: result = (WaveModifier *) WaveModifier_distortion_create(parameters.info.distortion.amplification, parameters.info.distortion.clipRange); break; case WAVE_MODIFIER_TYPE_HARMONICS: result = (WaveModifier *) WaveModifier_harmonics_create(parameters.info.harmonics.toneCount, parameters.info.harmonics.frequencySpacing, parameters.info.harmonics.falloff, parameters.info.harmonics.averageAmplitude); break; case WAVE_MODIFIER_TYPE_RESET: result = (WaveModifier *) WaveModifier_reset_create(parameters.info.reset.resetPoint); break; case WAVE_MODIFIER_TYPE_SUPERSAMPLE: result = (WaveModifier *) WaveModifier_supersample_create(parameters.info.supersample.sampleCount); break; case WAVE_MODIFIER_TYPE_CHORD: result = (WaveModifier *) WaveModifier_chord_create(parameters.info.chord.noteCount, parameters.info.chord.notes); break; case WAVE_MODIFIER_TYPE_PHASER: result = (WaveModifier *) WaveModifier_phaser_create(parameters.info.phaser.timeOffset, parameters.info.phaser.smooth, parameters.info.phaser.bufferSize); break; case WAVE_MODIFIER_TYPE_SFXRHIGHLOWPASS: result = (WaveModifier *) WaveModifier_sfxrHighLowpass_create(parameters.info.sfxrHighLowpass.lpCutoff, parameters.info.sfxrHighLowpass.lpRamp, parameters.info.sfxrHighLowpass.lpResonance, parameters.info.sfxrHighLowpass.hpCutoff, parameters.info.sfxrHighLowpass.hpRamp); break; case WAVE_MODIFIER_TYPE_HIGHLOWPASS: result = (WaveModifier *) WaveModifier_highLowpass_create(parameters.info.highLowpass.lpStrength, parameters.info.highLowpass.hpStrength); break; case WAVE_MODIFIER_TYPE_TIME_VALUE_TRANSFORM: result = (WaveModifier *) WaveModifier_timeValueTransform_create(parameters.info.timeValueTransform.timeOffset, parameters.info.timeValueTransform.timeScale, parameters.info.timeValueTransform.valueOffset, parameters.info.timeValueTransform.valueScale); break; case WAVE_MODIFIER_TYPE_THINNING: result = (WaveModifier *) WaveModifier_thinning_create(parameters.info.thinning.amount, parameters.info.thinning.center); break; case WAVE_MODIFIER_TYPE_TIME_CURVE: result = (WaveModifier *) WaveModifier_timeCurve_create(parameters.info.timeCurve.strength, parameters.info.timeCurve.center); break; case WAVE_MODIFIER_TYPE_RING_MODULATION: result = (WaveModifier *) WaveModifier_ringModulation_create(GeneralSynthConfiguration_createWaveSamplerFromParameters(*parameters.info.ringModulation.carrierParameters), parameters.info.ringModulation.carrierFrequency, parameters.info.ringModulation.carrierPhaseOffset); break; } if (result != NULL) { result->blend = parameters.blend; result->mute = parameters.mute; result->solo = parameters.solo; } return result; } void GeneralSynthConfiguration_serializeWaveModifierParameters(struct GeneralSynthConfiguration_waveModifierParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_waveModifier_formatType); call_virtual(writeString, context, "format_type", GeneralSynthConfiguration_waveModifier_formatType); call_virtual(writeUInt16, context, "format_version", GeneralSynthConfiguration_waveModifier_formatVersion); GeneralSynthConfiguration_serializeWaveModifierParametersMinimal(parameters, context); call_virtual(endStructure, context); } #define WAVE_MODIFIER_TYPE_ENUM_VALUES { \ {"distortion", WAVE_MODIFIER_TYPE_DISTORTION}, \ {"harmonics", WAVE_MODIFIER_TYPE_HARMONICS}, \ {"reset", WAVE_MODIFIER_TYPE_RESET}, \ {"supersample", WAVE_MODIFIER_TYPE_SUPERSAMPLE}, \ {"chord", WAVE_MODIFIER_TYPE_CHORD}, \ {"phaser", WAVE_MODIFIER_TYPE_PHASER}, \ {"highlowpass_sfxr", WAVE_MODIFIER_TYPE_SFXRHIGHLOWPASS}, \ {"highlowpass", WAVE_MODIFIER_TYPE_HIGHLOWPASS}, \ {"timevalue", WAVE_MODIFIER_TYPE_TIME_VALUE_TRANSFORM}, \ {"thinning", WAVE_MODIFIER_TYPE_THINNING}, \ {"time_curve", WAVE_MODIFIER_TYPE_TIME_CURVE}, \ {"ring_modulation", WAVE_MODIFIER_TYPE_RING_MODULATION} \ } void GeneralSynthConfiguration_serializeWaveModifierParametersMinimal(struct GeneralSynthConfiguration_waveModifierParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; Serialization_enumKeyValue waveModifierTypeValues[] = WAVE_MODIFIER_TYPE_ENUM_VALUES; call_virtual(writeEnumeration, context, "type", parameters.type, sizeof_count(waveModifierTypeValues), waveModifierTypeValues); call_virtual(writeFloat, context, "blend", parameters.blend); call_virtual(writeBoolean, context, "mute", parameters.mute); call_virtual(writeBoolean, context, "solo", parameters.solo); switch (parameters.type) { case WAVE_MODIFIER_TYPE_DISTORTION: call_virtual(writeFloat, context, "amplification", parameters.info.distortion.amplification); call_virtual(writeFloat, context, "clip_range", parameters.info.distortion.clipRange); break; case WAVE_MODIFIER_TYPE_HARMONICS: call_virtual(writeFloat, context, "tone_count", parameters.info.harmonics.toneCount); call_virtual(writeFloat, context, "frequency_spacing", parameters.info.harmonics.frequencySpacing); call_virtual(writeFloat, context, "falloff", parameters.info.harmonics.falloff); call_virtual(writeBoolean, context, "average_amplitude", parameters.info.harmonics.averageAmplitude); break; case WAVE_MODIFIER_TYPE_RESET: call_virtual(writeFloat, context, "reset_point", parameters.info.reset.resetPoint); break; case WAVE_MODIFIER_TYPE_SUPERSAMPLE: call_virtual(writeUInt8, context, "sample_count", parameters.info.supersample.sampleCount); break; case WAVE_MODIFIER_TYPE_CHORD: call_virtual(beginArray, context, "notes"); for (unsigned int noteIndex = 0; noteIndex < parameters.info.chord.noteCount; noteIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeInt16, context, "note", parameters.info.chord.notes[noteIndex].note); call_virtual(writeFloat, context, "amplitude", parameters.info.chord.notes[noteIndex].amplitude); call_virtual(endStructure, context); } call_virtual(endArray, context); break; case WAVE_MODIFIER_TYPE_PHASER: call_virtual(writeFloat, context, "time_offset", parameters.info.phaser.timeOffset); call_virtual(writeBoolean, context, "smooth", parameters.info.phaser.smooth); call_virtual(writeUInt32, context, "buffer_size", parameters.info.phaser.bufferSize); break; case WAVE_MODIFIER_TYPE_SFXRHIGHLOWPASS: call_virtual(writeFloat, context, "lp_cutoff", parameters.info.sfxrHighLowpass.lpCutoff); call_virtual(writeFloat, context, "lp_ramp", parameters.info.sfxrHighLowpass.lpRamp); call_virtual(writeFloat, context, "lp_resonance", parameters.info.sfxrHighLowpass.lpResonance); call_virtual(writeFloat, context, "hp_cutoff", parameters.info.sfxrHighLowpass.hpCutoff); call_virtual(writeFloat, context, "hp_ramp", parameters.info.sfxrHighLowpass.hpRamp); break; case WAVE_MODIFIER_TYPE_HIGHLOWPASS: call_virtual(writeFloat, context, "lp_strength", parameters.info.highLowpass.lpStrength); call_virtual(writeFloat, context, "hp_strength", parameters.info.highLowpass.hpStrength); break; case WAVE_MODIFIER_TYPE_TIME_VALUE_TRANSFORM: call_virtual(writeFloat, context, "time_offset", parameters.info.timeValueTransform.timeOffset); call_virtual(writeFloat, context, "time_scale", parameters.info.timeValueTransform.timeScale); call_virtual(writeFloat, context, "value_offset", parameters.info.timeValueTransform.valueOffset); call_virtual(writeFloat, context, "value_scale", parameters.info.timeValueTransform.valueScale); break; case WAVE_MODIFIER_TYPE_THINNING: call_virtual(writeFloat, context, "amount", parameters.info.thinning.amount); call_virtual(writeFloat, context, "center", parameters.info.thinning.center); break; case WAVE_MODIFIER_TYPE_TIME_CURVE: call_virtual(writeFloat, context, "strength", parameters.info.timeCurve.strength); call_virtual(writeFloat, context, "center", parameters.info.timeCurve.center); break; case WAVE_MODIFIER_TYPE_RING_MODULATION: call_virtual(writeFloat, context, "frequency", parameters.info.ringModulation.carrierFrequency); call_virtual(writeFloat, context, "offset", parameters.info.ringModulation.carrierPhaseOffset); GeneralSynthConfiguration_serializeWaveParametersMinimal(*parameters.info.ringModulation.carrierParameters, context); break; } } bool GeneralSynthConfiguration_deserializeWaveModifierParameters(compat_type(DeserializationContext *) deserializationContext, struct GeneralSynthConfiguration_waveModifierParameters * outParameters) { DeserializationContext * context = deserializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_waveModifier_formatType); const char * formatType = call_virtual(readString, context, "format_type"); if (formatType == NULL || strcmp(formatType, GeneralSynthConfiguration_waveModifier_formatType)) { return false; } uint16_t formatVersion = call_virtual(readUInt16, context, "format_version"); if (formatVersion > GeneralSynthConfiguration_waveModifier_formatVersion) { return false; } bool success = GeneralSynthConfiguration_deserializeWaveModifierParametersMinimal(context, formatVersion, outParameters); call_virtual(endStructure, context); return success; } bool GeneralSynthConfiguration_deserializeWaveModifierParametersMinimal(compat_type(DeserializationContext *) deserializationContext, uint16_t formatVersion, struct GeneralSynthConfiguration_waveModifierParameters * outParameters) { DeserializationContext * context = deserializationContext; struct GeneralSynthConfiguration_waveModifierParameters parameters; Serialization_enumKeyValue waveModifierTypeValues[] = WAVE_MODIFIER_TYPE_ENUM_VALUES; parameters.type = call_virtual(readEnumeration, context, "type", sizeof_count(waveModifierTypeValues), waveModifierTypeValues); parameters.blend = call_virtual(readFloat, context, "blend"); parameters.mute = call_virtual(readBoolean, context, "mute"); parameters.solo = call_virtual(readBoolean, context, "solo"); switch (parameters.type) { case WAVE_MODIFIER_TYPE_DISTORTION: parameters.info.distortion.amplification = call_virtual(readFloat, context, "amplification"); parameters.info.distortion.clipRange = call_virtual(readFloat, context, "clip_range"); break; case WAVE_MODIFIER_TYPE_HARMONICS: parameters.info.harmonics.toneCount = call_virtual(readFloat, context, "tone_count"); parameters.info.harmonics.frequencySpacing = call_virtual(readFloat, context, "frequency_spacing"); parameters.info.harmonics.falloff = call_virtual(readFloat, context, "falloff"); parameters.info.harmonics.averageAmplitude = call_virtual(readBoolean, context, "average_amplitude"); break; case WAVE_MODIFIER_TYPE_RESET: parameters.info.reset.resetPoint = call_virtual(readFloat, context, "reset_point"); break; case WAVE_MODIFIER_TYPE_SUPERSAMPLE: parameters.info.supersample.sampleCount = call_virtual(readUInt16, context, "sample_count"); break; case WAVE_MODIFIER_TYPE_CHORD: parameters.info.chord.noteCount = call_virtual(beginArray, context, "notes"); if (parameters.info.chord.noteCount == 0) { parameters.info.chord.notes = NULL; } else { parameters.info.chord.notes = malloc(parameters.info.chord.noteCount * sizeof(*parameters.info.chord.notes)); for (unsigned int noteIndex = 0; noteIndex < parameters.info.chord.noteCount; noteIndex++) { call_virtual(beginStructure, context, NULL); parameters.info.chord.notes[noteIndex].note = call_virtual(readInt16, context, "note"); parameters.info.chord.notes[noteIndex].amplitude = call_virtual(readFloat, context, "amplitude"); call_virtual(endStructure, context); } } call_virtual(endArray, context); break; case WAVE_MODIFIER_TYPE_PHASER: parameters.info.phaser.timeOffset = call_virtual(readFloat, context, "time_offset"); parameters.info.phaser.smooth = call_virtual(readBoolean, context, "smooth"); parameters.info.phaser.bufferSize = call_virtual(readUInt32, context, "buffer_size"); break; case WAVE_MODIFIER_TYPE_SFXRHIGHLOWPASS: parameters.info.sfxrHighLowpass.lpCutoff = call_virtual(readFloat, context, "lp_cutoff"); parameters.info.sfxrHighLowpass.lpRamp = call_virtual(readFloat, context, "lp_ramp"); parameters.info.sfxrHighLowpass.lpResonance = call_virtual(readFloat, context, "lp_resonance"); parameters.info.sfxrHighLowpass.hpCutoff = call_virtual(readFloat, context, "hp_cutoff"); parameters.info.sfxrHighLowpass.hpRamp = call_virtual(readFloat, context, "hp_ramp"); break; case WAVE_MODIFIER_TYPE_HIGHLOWPASS: parameters.info.highLowpass.lpStrength = call_virtual(readFloat, context, "lp_strength"); parameters.info.highLowpass.hpStrength = call_virtual(readFloat, context, "hp_strength"); break; case WAVE_MODIFIER_TYPE_TIME_VALUE_TRANSFORM: parameters.info.timeValueTransform.timeOffset = call_virtual(readFloat, context, "time_offset"); parameters.info.timeValueTransform.timeScale = call_virtual(readFloat, context, "time_scale"); parameters.info.timeValueTransform.valueOffset = call_virtual(readFloat, context, "value_offset"); parameters.info.timeValueTransform.valueScale = call_virtual(readFloat, context, "value_scale"); break; case WAVE_MODIFIER_TYPE_THINNING: parameters.info.thinning.amount = call_virtual(readFloat, context, "amount"); parameters.info.thinning.center = call_virtual(readFloat, context, "center"); break; case WAVE_MODIFIER_TYPE_TIME_CURVE: parameters.info.timeCurve.strength = call_virtual(readFloat, context, "strength"); parameters.info.timeCurve.center = call_virtual(readFloat, context, "center"); break; case WAVE_MODIFIER_TYPE_RING_MODULATION: parameters.info.ringModulation.carrierFrequency = call_virtual(readFloat, context, "frequency"); parameters.info.ringModulation.carrierPhaseOffset = call_virtual(readFloat, context, "offset"); parameters.info.ringModulation.carrierParameters = malloc(sizeof(*parameters.info.ringModulation.carrierParameters)); GeneralSynthConfiguration_deserializeWaveParametersMinimal(context, formatVersion, parameters.info.ringModulation.carrierParameters); break; } if (context->status != SERIALIZATION_ERROR_OK) { GeneralSynthConfiguration_disposeWaveModifierParameters(parameters); return false; } *outParameters = parameters; return true; } void GeneralSynthConfiguration_disposeWaveModifierParameters(struct GeneralSynthConfiguration_waveModifierParameters parameters) { switch (parameters.type) { case WAVE_MODIFIER_TYPE_DISTORTION: case WAVE_MODIFIER_TYPE_HARMONICS: case WAVE_MODIFIER_TYPE_RESET: case WAVE_MODIFIER_TYPE_SUPERSAMPLE: case WAVE_MODIFIER_TYPE_PHASER: case WAVE_MODIFIER_TYPE_SFXRHIGHLOWPASS: case WAVE_MODIFIER_TYPE_HIGHLOWPASS: case WAVE_MODIFIER_TYPE_TIME_VALUE_TRANSFORM: case WAVE_MODIFIER_TYPE_THINNING: case WAVE_MODIFIER_TYPE_TIME_CURVE: break; case WAVE_MODIFIER_TYPE_CHORD: free(parameters.info.chord.notes); break; case WAVE_MODIFIER_TYPE_RING_MODULATION: GeneralSynthConfiguration_disposeWaveParameters(*parameters.info.ringModulation.carrierParameters); free(parameters.info.ringModulation.carrierParameters); break; } } GeneralSynthConfiguration_waveModifierType getWaveModifierType(WaveModifier * waveModifier) { if (StemObject_isExactClass(waveModifier, &WaveModifier_distortion_class)) { return WAVE_MODIFIER_TYPE_DISTORTION; } if (StemObject_isExactClass(waveModifier, &WaveModifier_harmonics_class)) { return WAVE_MODIFIER_TYPE_HARMONICS; } if (StemObject_isExactClass(waveModifier, &WaveModifier_reset_class)) { return WAVE_MODIFIER_TYPE_RESET; } if (StemObject_isExactClass(waveModifier, &WaveModifier_supersample_class)) { return WAVE_MODIFIER_TYPE_SUPERSAMPLE; } if (StemObject_isExactClass(waveModifier, &WaveModifier_chord_class)) { return WAVE_MODIFIER_TYPE_CHORD; } if (StemObject_isExactClass(waveModifier, &WaveModifier_phaser_class)) { return WAVE_MODIFIER_TYPE_PHASER; } if (StemObject_isExactClass(waveModifier, &WaveModifier_sfxrHighLowpass_class)) { return WAVE_MODIFIER_TYPE_SFXRHIGHLOWPASS; } if (StemObject_isExactClass(waveModifier, &WaveModifier_highLowpass_class)) { return WAVE_MODIFIER_TYPE_HIGHLOWPASS; } if (StemObject_isExactClass(waveModifier, &WaveModifier_timeValueTransform_class)) { return WAVE_MODIFIER_TYPE_TIME_VALUE_TRANSFORM; } if (StemObject_isExactClass(waveModifier, &WaveModifier_thinning_class)) { return WAVE_MODIFIER_TYPE_THINNING; } if (StemObject_isExactClass(waveModifier, &WaveModifier_timeCurve_class)) { return WAVE_MODIFIER_TYPE_TIME_CURVE; } if (StemObject_isExactClass(waveModifier, &WaveModifier_ringModulation_class)) { return WAVE_MODIFIER_TYPE_RING_MODULATION; } #ifdef DEBUG fprintf(stderr, "Warning: Unknown wave modifier class %p passed to getWaveModifierType\n", waveModifier->vtable); #endif return WAVE_MODIFIER_TYPE_DISTORTION; } const char * getWaveModifierHumanReadableName(GeneralSynthConfiguration_waveModifierType type) { switch (type) { case WAVE_MODIFIER_TYPE_DISTORTION: return "Distortion"; case WAVE_MODIFIER_TYPE_HARMONICS: return "Harmonics"; case WAVE_MODIFIER_TYPE_RESET: return "Reset"; case WAVE_MODIFIER_TYPE_SUPERSAMPLE: return "Supersample"; case WAVE_MODIFIER_TYPE_CHORD: return "Chord"; case WAVE_MODIFIER_TYPE_PHASER: return "Phaser"; case WAVE_MODIFIER_TYPE_SFXRHIGHLOWPASS: return "High/lowpass (SFXR)"; case WAVE_MODIFIER_TYPE_HIGHLOWPASS: return "High/lowpass"; case WAVE_MODIFIER_TYPE_TIME_VALUE_TRANSFORM: return "Time/value transform"; case WAVE_MODIFIER_TYPE_THINNING: return "Thinning"; case WAVE_MODIFIER_TYPE_TIME_CURVE: return "Time curve"; case WAVE_MODIFIER_TYPE_RING_MODULATION: return "Ring modulation"; } return "(unknown)"; } struct GeneralSynthConfiguration_synthPropertyControllerParameters GeneralSynthConfiguration_createSynthPropertyControllerParametersFromController(compat_type(SynthPropertyController *) controller) { struct GeneralSynthConfiguration_synthPropertyControllerParameters parameters; parameters.type = getSynthPropertyControllerType(controller); parameters.identifier = ((SynthPropertyController *) controller)->propertyIdentifier; parameters.mute = ((SynthPropertyController *) controller)->mute; parameters.solo = ((SynthPropertyController *) controller)->solo; switch (parameters.type) { case SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP: { SynthPropertyController_ramp * controllerTyped = controller; parameters.info.ramp.startValue = controllerTyped->startValue; parameters.info.ramp.endValue = controllerTyped->endValue; parameters.info.ramp.curvePower = controllerTyped->curvePower; parameters.info.ramp.onset = controllerTyped->onset; parameters.info.ramp.endpoint = controllerTyped->endpoint; parameters.info.ramp.resetPoint = controllerTyped->resetPoint; break; } case SYNTH_PROPERTY_CONTROLLER_TYPE_SINE: { SynthPropertyController_sine * controllerTyped = controller; parameters.info.sine.centerValue = controllerTyped->centerValue; parameters.info.sine.amplitude = controllerTyped->amplitude; parameters.info.sine.cycleCount = controllerTyped->cycleCount; parameters.info.sine.startPhase = controllerTyped->startPhase; break; } } return parameters; } SynthPropertyController * GeneralSynthConfiguration_createSynthPropertyControllerFromParameters(struct GeneralSynthConfiguration_synthPropertyControllerParameters parameters) { SynthPropertyController * result = NULL; switch (parameters.type) { case SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP: result = (SynthPropertyController *) SynthPropertyController_ramp_create(parameters.identifier, parameters.info.ramp.startValue, parameters.info.ramp.endValue, parameters.info.ramp.curvePower, parameters.info.ramp.onset, parameters.info.ramp.endpoint, parameters.info.ramp.resetPoint); break; case SYNTH_PROPERTY_CONTROLLER_TYPE_SINE: result = (SynthPropertyController *) SynthPropertyController_sine_create(parameters.identifier, parameters.info.sine.centerValue, parameters.info.sine.amplitude, parameters.info.sine.cycleCount, parameters.info.sine.startPhase); break; } if (result != NULL) { result->mute = parameters.mute; result->solo = parameters.solo; } return result; } void GeneralSynthConfiguration_serializeSynthPropertyControllerParameters(struct GeneralSynthConfiguration_synthPropertyControllerParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_synthPropertyController_formatType); call_virtual(writeString, context, "format_type", GeneralSynthConfiguration_synthPropertyController_formatType); call_virtual(writeUInt16, context, "format_version", GeneralSynthConfiguration_synthPropertyController_formatVersion); GeneralSynthConfiguration_serializeSynthPropertyControllerParametersMinimal(parameters, context); call_virtual(endStructure, context); } #define CONTROLLER_TYPE_ENUM_VALUES { \ {"ramp", SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP}, \ {"sine", SYNTH_PROPERTY_CONTROLLER_TYPE_SINE} \ } #define CONTROLLER_ROOT_TYPE_ENUM_VALUES { \ {"undefined", SYNTH_PROPERTY_ROOT_UNDEFINED}, \ {"amplitude", SYNTH_PROPERTY_ROOT_AMPLITUDE_ENVELOPE}, \ {"frequency", SYNTH_PROPERTY_ROOT_FREQUENCY_CURVE}, \ {"wave", SYNTH_PROPERTY_ROOT_WAVE_SAMPLER}, \ {"signal_filter", SYNTH_PROPERTY_ROOT_SIGNAL_FILTER} \ } void GeneralSynthConfiguration_serializeSynthPropertyControllerParametersMinimal(struct GeneralSynthConfiguration_synthPropertyControllerParameters parameters, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; Serialization_enumKeyValue controllerTypeValues[] = CONTROLLER_TYPE_ENUM_VALUES; call_virtual(writeEnumeration, context, "type", parameters.type, sizeof_count(controllerTypeValues), controllerTypeValues); Serialization_enumKeyValue controllerRootTypeValues[] = CONTROLLER_ROOT_TYPE_ENUM_VALUES; call_virtual(writeEnumeration, context, "root_type", parameters.identifier.rootType, sizeof_count(controllerRootTypeValues), controllerRootTypeValues); call_virtual(writeUInt16, context, "object_index", parameters.identifier.objectIndex); call_virtual(writeUInt16, context, "property_index", parameters.identifier.propertyIndex); call_virtual(writeBoolean, context, "mute", parameters.mute); call_virtual(writeBoolean, context, "solo", parameters.solo); switch (parameters.type) { case SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP: call_virtual(writeFloat, context, "start_value", parameters.info.ramp.startValue); call_virtual(writeFloat, context, "end_value", parameters.info.ramp.endValue); call_virtual(writeFloat, context, "curve_power", parameters.info.ramp.curvePower); call_virtual(writeFloat, context, "onset", parameters.info.ramp.onset); call_virtual(writeFloat, context, "endpoint", parameters.info.ramp.endpoint); call_virtual(writeFloat, context, "reset_point", parameters.info.ramp.resetPoint); break; case SYNTH_PROPERTY_CONTROLLER_TYPE_SINE: call_virtual(writeFloat, context, "center_value", parameters.info.sine.centerValue); call_virtual(writeFloat, context, "amplitude", parameters.info.sine.amplitude); call_virtual(writeFloat, context, "cycle_count", parameters.info.sine.cycleCount); call_virtual(writeFloat, context, "start_phase", parameters.info.sine.startPhase); break; } } bool GeneralSynthConfiguration_deserializeSynthPropertyControllerParameters(compat_type(DeserializationContext *) deserializationContext, struct GeneralSynthConfiguration_synthPropertyControllerParameters * outParameters) { DeserializationContext * context = deserializationContext; call_virtual(beginStructure, context, GeneralSynthConfiguration_waveModifier_formatType); const char * formatType = call_virtual(readString, context, "format_type"); if (formatType == NULL || strcmp(formatType, GeneralSynthConfiguration_synthPropertyController_formatType)) { return false; } uint16_t formatVersion = call_virtual(readUInt16, context, "format_version"); if (formatVersion > GeneralSynthConfiguration_synthPropertyController_formatVersion) { return false; } bool success = GeneralSynthConfiguration_deserializeSynthPropertyControllerParametersMinimal(context, formatVersion, outParameters); call_virtual(endStructure, context); return success; } bool GeneralSynthConfiguration_deserializeSynthPropertyControllerParametersMinimal(compat_type(DeserializationContext *) deserializationContext, uint16_t formatVersion, struct GeneralSynthConfiguration_synthPropertyControllerParameters * outParameters) { DeserializationContext * context = deserializationContext; struct GeneralSynthConfiguration_synthPropertyControllerParameters parameters; Serialization_enumKeyValue controllerTypeValues[] = CONTROLLER_TYPE_ENUM_VALUES; parameters.type = call_virtual(readEnumeration, context, "type", sizeof_count(controllerTypeValues), controllerTypeValues); Serialization_enumKeyValue controllerRootTypeValues[] = CONTROLLER_ROOT_TYPE_ENUM_VALUES; parameters.identifier.rootType = call_virtual(readEnumeration, context, "root_type", sizeof_count(controllerRootTypeValues), controllerRootTypeValues); parameters.identifier.objectIndex = call_virtual(readUInt16, context, "object_index"); parameters.identifier.propertyIndex = call_virtual(readUInt16, context, "property_index"); parameters.mute = call_virtual(readBoolean, context, "mute"); parameters.solo = call_virtual(readBoolean, context, "solo"); switch (parameters.type) { case SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP: parameters.info.ramp.startValue = call_virtual(readFloat, context, "start_value"); parameters.info.ramp.endValue = call_virtual(readFloat, context, "end_value"); parameters.info.ramp.curvePower = call_virtual(readFloat, context, "curve_power"); parameters.info.ramp.onset = call_virtual(readFloat, context, "onset"); parameters.info.ramp.endpoint = call_virtual(readFloat, context, "endpoint"); parameters.info.ramp.resetPoint = call_virtual(readFloat, context, "reset_point"); break; case SYNTH_PROPERTY_CONTROLLER_TYPE_SINE: parameters.info.sine.centerValue = call_virtual(readFloat, context, "center_value"); parameters.info.sine.amplitude = call_virtual(readFloat, context, "amplitude"); parameters.info.sine.cycleCount = call_virtual(readFloat, context, "cycle_count"); parameters.info.sine.startPhase = call_virtual(readFloat, context, "start_phase"); break; } if (context->status != SERIALIZATION_ERROR_OK) { GeneralSynthConfiguration_disposeSynthPropertyControllerParameters(parameters); return false; } *outParameters = parameters; return true; } void GeneralSynthConfiguration_disposeSynthPropertyControllerParameters(struct GeneralSynthConfiguration_synthPropertyControllerParameters parameters) { switch (parameters.type) { case SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP: case SYNTH_PROPERTY_CONTROLLER_TYPE_SINE: break; } } GeneralSynthConfiguration_synthPropertyControllerType getSynthPropertyControllerType(SynthPropertyController * controller) { if (StemObject_isExactClass(controller, &SynthPropertyController_ramp_class)) { return SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP; } if (StemObject_isExactClass(controller, &SynthPropertyController_sine_class)) { return SYNTH_PROPERTY_CONTROLLER_TYPE_SINE; } #ifdef DEBUG fprintf(stderr, "Warning: Unknown property controller class %p passed to getSynthPropertyControllerType\n", controller->vtable); #endif return SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP; } const char * getSynthPropertyControllerHumanReadableName(GeneralSynthConfiguration_synthPropertyControllerType type) { switch (type) { case SYNTH_PROPERTY_CONTROLLER_TYPE_RAMP: return "Ramp"; case SYNTH_PROPERTY_CONTROLLER_TYPE_SINE: return "Sine"; } return "(unknown)"; }