Previous topic

Granular Synthesis

Next topic

Core Blocks

This Page

Frequency Domain

constant Size { value: 1024 }

signal InputBuffer [Size] { default: 0.0 rate: none }
signal OutputBuffer [Size] { default: 0.0 rate: none }

complex Spectrum [ Size / 2 + 1] { default: [ 0.0, 0.0 ] rate: AudioRate / ( Size / 2 ) }
complex BrickWall [ Size / 2 + 1] { default: [ 0.0, 0.0 ] rate: none }

[ 1.0, 1.0 ] >> BrickWall [ 1 : Size / 4 ];

InputBuffer >> RealFFT () >> Spectrum;

[ Spectrum, BrickWall ] >> CxMultiply () >> RealIFFT () >> OutputBuffer;

AudioIn >> FillBundle ( size: Size hopSize: Size / 2 ) >> InputBuffer;

OutputBuffer >> OverlapAdd ( size: Size overlapSize: Size / 2 ) >> GetSample ( size: Size ) >> AudioOut;

Module: FillBundle

module FillBundle {
        input:                  Input
        output:                 Outputs
        propertyName:           [ 'size', 'hopSize' ]
        propertyDirection:      in
        propertyBlock:          [
                constant Size { value: 128 },
                constant HopSize { value: Size / 2 }
        ]
        constraints:            [
                Size >> Compare ( value: 1 operator: 'LessOrEqual' ) >> Error ( message: "'size' should be a positive integer greater than one" );
                HopSize >> Compare (value: 0 operator: 'LessOrEqual' ) >> Error ( message: "'hopSize' should be a positive integer" );
                HopSize >> Compare (value: Size operator: 'Greater' ) >> Error ( message: "'hopSize' should be less than 'size'"        );
        ]
        internalBlock:          [
                signal Input { rate: none },
                signal Outputs [Size] { rate: none },
                signal Samples [Size] { rate: none },
                signal Index { default: 1 rate: none reset: ResetIndex },
                signal SampleCount { default: 0 rate: none reset: ResetSampleCount },
                reaction RenderBuffer {
                        output:         Outputs
                        onExecution:    Reset
                        terminateWhen:  Done
                        internalBlocks: [
                                signal Outputs [Size] { rate: none },
                                switch Done { default: off reset: Reset },
                                trigger Reset {}
                        ]
                        streams:        [
                                Index
                                >> Compare ( value: 1 operator: 'Equal' )
                                >> Select (
                                        whenOn:         Samples
                                        whenOff:        [ Samples[ Index : Size ], Samples[ 1 : Index - 1 ] ]                   # MANY TO ONE CONNECTION // signal SortIndex needed
                                )
                                >> Outputs;

                                on >> Done;
                        ]
                        },
                trigger ResetIndex {},
                trigger ResetSampleCount {}
        ]
        streams:                [
                Input >> Samples [Index];
                Index + 1 >> Index >> Compare ( value: Size operator: 'Greater' ) >> ResetIndex;
                SampleCount + 1 >>  SampleCount  >> Compare ( value: HopSize operator: 'Equal' ) >> ResetSampleCount >> RenderBuffer () >> Outputs;
        ]
}

Module: OverlapAdd

module OverlapAdd {
        input:                  Inputs
        output:                 Outputs
        propertyName:           [ 'size', 'overlapSize' ]
        propertyDirection:      in
        propertyBlock:          [
                constant Size { value: 128 },
                constant OverlapSize { value: Size / 2 },
        ]
        constraints:            none
        internalBlock:          [
                signal Inputs [Size] { rate: none },
                signal Outputs [Size] { rate: none },
                signal Index { default: 1 rate: none reset: ResetIndex },
                trigger ResetIndex {},
                reaction RenderBuffer {
                        output:         RenderedBuffer
                        onExecution:    ResetReadIndex
                        terminateWhen:  RenderingComplete
                        internalBlock:  [
                                signal RenderedBuffer [Size] { rate: none },
                                signal WriteIndex { default: 1 rate: none reset: ResetWriteIndex },
                                signal ReadIndex { default: 1 rate: none reset: ResetReadIndex },
                                signal ValueWhenOn { rate: none },
                                signal ValueWhenOff { rate: none },
                                trigger ResetWriteIndex {},
                                trigger ResetReadIndex {},
                                trigger RenderingComplete {}
                        ]
                        streams:        [
                                ReadIndex
                                >> Compare ( value: 1 operator: 'Equal' )
                                >> Select (
                                        whenOn:         Index
                                        whenOff:        WriteIndex + 1
                                )
                                >> WriteIndex
                                >> Compare ( value: Size operator: 'Greater' )
                                >> ResetWriteIndex;

                                Inputs >>  GetPort ( index: ReadIndex ) >> ValueWhenOn;

                                [ Inputs , Outputs ] >> GetPort ( index: [ ReadIndex, WriteIndex] ) >> Add () >> ValueWhenOff;

                                ReadIndex
                                >> Compare ( value: Size - OverlapSize operator: 'Greater' )
                                >> Select (
                                        whenOn:         ValueWhenOn
                                        whenOff:        ValueWhenOff
                                )
                                >> SetPort ( index: WriteIndex )
                                >> RenderedBuffer;

                                ReadIndex + 1 >> ReadIndex >> Compare ( value: Size  operator: 'Greater' ) >> RenderingComplete;
                        ]
                }
        ]
        streams:                [
                RenderBuffer () >> Outputs;
                Index + OverlapSize >> Index >> Compare ( value: Size operator: 'Greater' ) >> ResetIndex;
        ]
}

Module: GetSample

module GetSample {
        input:                  Input
        output:                 Output
        propertyName:           'size'
        propertyDirection:      in
        propertyBlock:          constant Size { value: 128 }
        constraints:            Size >> Compare ( value: 1 operator: 'LessOrEqual' ) >> Error ( message: "'size' should be a positive integer greater than one" );
        internalBlock:          [
                signal Input [Size] { rate: none },
                signal Output { rate: streamRate },
                signal Index { default: 1 rate: streamRate reset: ResetIndex },
                trigger ResetIndex {}
        ]
        streams:                [
                Input[Index] >> Output;
                Index + 1 >> Index >> Compare ( value: Size operator: 'Greater' ) >> ResetIndex;
        ]
}