Synchronous Generation and Static Allocation
constant NumberOfGrains { value: 50 }
constant GrainTriggerRate { value: 15 }
constant GrainDuration { value: 4.0 }
constant GrainFrequency { value: 220 }
switch GrainState [NumberOfGrains] { default: off reset: ResetGrainState }
switch AllGrainsActive { default: off reset: none}
trigger ResetGrainState [NumberOfGrains] {}
signal ImpulseTrainSignal { default: 0.0 rate: AudioRate domain: AudioDomain }
reaction RequestGrain {
output: Index
onExecution: ResetGrainIndex
terminateWhen: FreeGrainFound or NoFreeGrainAvailable
internalBlock: [
signal Index { default: 1 rate: none domain: AudioDomain reset: ResetGrainIndex },
trigger ResetGrainIndex {},
trigger FreeGrainFound {},
trigger NoFreeGrainAvailable {}
]
streams: [
GrainState[Index] >> Select ( whenOn: on whenOff: on ) >> GrainState[Index] >> FreeGrainFound;
Index + 1 >> Index >> Compare ( value: Size operator: 'Greater' ) >> NoFreeGrainAvailable;
]
}
Oscillator (
type: 'Sine'
frequency: GrainFrequency
reset: GrainState
)
>> Envelope (
type: 'Gaussian'
size: GrainDuration * streamRate / 1000.0
reset: GrainState
complete: ResetGrainState
)
>> Mix ()
>> Level ( gain: 1.0 / NumberOfGrains ) # Add a smoothing function here
>> AudioOut[1:2];
ImpulseTrain ( frequency: GrainTriggerRate ) >> ImpulseTrainSignal;
GrainState >> And () >> AllGrainsActive;
ImpulseTrainSignal and not AllGrainsActive >> RequestGrain (); # The output port is left unconnected
Synchronous Generation and Dynamic Allocation
constant GrainTriggerRate { value: 15 }
constant GrainDuration { value: 4.0 }
constant GrainFrequency { value: 220 }
constant Zero { value: 0.0 }
variable Grains { count: GrainCount createWhen: AddGrain destroyWhen: RemoveGrain }
signal GrainCount { default: 0 rate: none domain: AudioDomain }
trigger AddGrain {}
trigger RemoveGrain [Grains] {}
signal ImpulseTrainStream { default: 0.0 rate: AudioRate reset: none domain: AudioDomain}
signal PortSelect { default: 1 rate: AudioRate reset: none domain: AudioDomain }
ImpulseTrain ( frequency: GrainTriggerRate ) >> ImpulseTrainStream >> AddGrain;
GrainCount >> Compare ( value: 0 operator: 'Equal' ) >> Select ( whenOn: 1 whenOff: 2 ) >> PortSelect;
[
Zero
,
Oscillator (
type: 'Sine'
frequency: GrainFrequency
)
>> Envelope (
type: 'Gaussian'
size: GrainDuration * streamRate / 1000.0
complete: RemoveGrain
)
>> Mix ()
>> Level ( gain: 1.0 / GrainCount ) # Add a smoothing function here
]
>> GetPort ( index: PortSelect )
>> AudioOut[1:2];
Synchronous Generation and Dynamic Allocation with Control
constant GrainTriggerRate { value: 15 }
constant Zero { value: 0.0 }
variable Grains { count: GrainCount createWhen: AddGrain destroyWhen: RemoveGrain }
signal GrainCount { default: 0 domain: AudioDomain }
trigger AddGrain {}
trigger RemoveGrain [Grains] {}
signal GrainDuration [Grains] { default: 4.0 rate: none }
signal GrainFrequency [Grains] { default: 15 rate: none }
signal ImpulseTrainStream { default: 0.0 rate: AudioRate reset: none domain: AudioDomain }
signal PortSelect { default: 1 rate: AudioRate reset: none domain: AudioDomain }
reaction CaptureControls {
output: none
onExecution: Reset
terminateWhen: Captured
internalBlock: [
switch Capture { default: off reset: Reset },
trigger Reset {}
]
streams: [
ControlIn [1:2]
>> Map ( minimum: [ 1, 55.0 ] maximum: [ 200, 880.0 ] )
>> SampleHold ( event: Reset )
>> [ GrainDuration [GrainCount], GrainFrequency [ GrainCount ];
on >> Captured;
]
}
ImpulseTrain ( frequency: GrainTriggerRate ) >> ImpulseTrainStream >> AddGrain >> CaptureControls ();
GrainCount >> Compare ( value: 0 operator: 'Equal' ) >> Select ( whenOn: 1 whenOff: 2 ) >> PortSelect;
[
Zero
,
Oscillator (
type: 'Sine'
frequency: GrainFrequency
)
>> Envelope (
type: 'Gaussian'
size: GrainDuration * streamRate / 1000.0
complete: RemoveGrain
)
>> Mix ()
>> Level ( gain: 1.0 / GrainCount ) # Add a smoothing function here
]
>> GetPort ( index: PortSelect )
>> AudioOut[1:2];