diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 76e5a44..0000000 --- a/.clang-format +++ /dev/null @@ -1,274 +0,0 @@ ---- -Language: Cpp -AccessModifierOffset: -4 -AlignAfterOpenBracket: DontAlign -AlignArrayOfStructures: None -AlignConsecutiveAssignments: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: true -AlignConsecutiveBitFields: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveDeclarations: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveMacros: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveShortCaseStatements: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCaseArrows: false - AlignCaseColons: false -AlignConsecutiveTableGenBreakingDAGArgColons: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveTableGenCondOperatorColons: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveTableGenDefinitionColons: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignEscapedNewlines: Right -AlignOperands: DontAlign -AlignTrailingComments: - Kind: Never - OverEmptyLines: 0 -AllowAllArgumentsOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowBreakBeforeNoexceptSpecifier: Never -AllowShortBlocksOnASingleLine: Empty -AllowShortCaseExpressionOnASingleLine: true -AllowShortCaseLabelsOnASingleLine: false -AllowShortCompoundRequirementOnASingleLine: true -AllowShortEnumsOnASingleLine: true -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AttributeMacros: - - __capability -BinPackArguments: true -BinPackParameters: true -BitFieldColonSpacing: Both -BraceWrapping: - AfterCaseLabel: false - AfterClass: false - AfterControlStatement: Never - AfterEnum: false - AfterExternBlock: false - AfterFunction: true - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - BeforeCatch: false - BeforeElse: false - BeforeLambdaBody: false - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true -BreakAdjacentStringLiterals: true -BreakAfterAttributes: Leave -BreakAfterJavaFieldAnnotations: false -BreakAfterReturnType: None -BreakArrays: true -BreakBeforeBinaryOperators: All -BreakBeforeConceptDeclarations: Always -BreakBeforeBraces: WebKit -BreakBeforeInlineASMColon: OnlyMultiline -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeComma -BreakFunctionDefinitionParameters: false -BreakInheritanceList: BeforeColon -BreakStringLiterals: true -BreakTemplateDeclarations: MultiLine -ColumnLimit: 0 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: false -DerivePointerAlignment: false -DisableFormat: false -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: LogicalBlock -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: false -ForEachMacros: - - foreach - - Q_FOREACH - - BOOST_FOREACH -IfMacros: - - KJ_IF_MAYBE -IncludeBlocks: Preserve -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - SortPriority: 0 - CaseSensitive: false - - Regex: '^(<|"(gtest|gmock|isl|json)/)' - Priority: 3 - SortPriority: 0 - CaseSensitive: false - - Regex: '.*' - Priority: 1 - SortPriority: 0 - CaseSensitive: false -IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' -IndentAccessModifiers: false -IndentCaseBlocks: false -IndentCaseLabels: false -IndentExternBlock: AfterExternBlock -IndentGotoLabels: true -IndentPPDirectives: None -IndentRequiresClause: true -IndentWidth: 4 -IndentWrappedFunctionNames: false -InsertBraces: false -InsertNewlineAtEOF: false -InsertTrailingCommas: None -IntegerLiteralSeparator: - Binary: 0 - BinaryMinDigits: 0 - Decimal: 0 - DecimalMinDigits: 0 - Hex: 0 - HexMinDigits: 0 -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLines: - AtEndOfFile: false - AtStartOfBlock: true - AtStartOfFile: true -LambdaBodyIndentation: Signature -LineEnding: DeriveLF -MacroBlockBegin: '' -MacroBlockEnd: '' -MainIncludeChar: Quote -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: Inner -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 4 -ObjCBreakBeforeNestedBlockParam: true -ObjCSpaceAfterProperty: true -ObjCSpaceBeforeProtocolList: true -PackConstructorInitializers: BinPack -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakOpenParenthesis: 0 -PenaltyBreakScopeResolution: 500 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyIndentedWhitespace: 0 -PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Left -PPIndentWidth: -1 -QualifierAlignment: Leave -ReferenceAlignment: Pointer -ReflowComments: true -RemoveBracesLLVM: false -RemoveParentheses: Leave -RemoveSemicolon: false -RequiresClausePosition: OwnLine -RequiresExpressionIndentation: OuterScope -SeparateDefinitionBlocks: Leave -ShortNamespaceLines: 1 -SkipMacroDefinitionBody: false -SortIncludes: CaseSensitive -SortJavaStaticImport: Before -SortUsingDeclarations: LexicographicNumeric -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: true -SpaceAroundPointerQualifiers: Default -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -SpaceBeforeCpp11BracedList: true -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeJsonColon: false -SpaceBeforeParens: ControlStatements -SpaceBeforeParensOptions: - AfterControlStatements: true - AfterForeachMacros: true - AfterFunctionDefinitionName: false - AfterFunctionDeclarationName: false - AfterIfMacros: true - AfterOverloadedOperator: false - AfterPlacementOperator: true - AfterRequiresInClause: false - AfterRequiresInExpression: false - BeforeNonEmptyParentheses: false -SpaceBeforeRangeBasedForLoopColon: true -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: true -SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never -SpacesInContainerLiterals: true -SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: -1 -SpacesInParens: Never -SpacesInParensOptions: - ExceptDoubleParentheses: false - InCStyleCasts: false - InConditionalStatements: false - InEmptyParentheses: false - Other: false -SpacesInSquareBrackets: false -Standard: Latest -StatementAttributeLikeMacros: - - Q_EMIT -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION -TableGenBreakInsideDAGArg: DontBreak -TabWidth: 8 -UseTab: Never -VerilogBreakBetweenInstancePorts: true -WhitespaceSensitiveMacros: - - BOOST_PP_STRINGIZE - - CF_SWIFT_NAME - - NS_SWIFT_NAME - - PP_STRINGIZE - - STRINGIZE -... - diff --git a/.gitignore b/.gitignore deleted file mode 100644 index dee53c5..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build -*~ diff --git a/controller.c b/controller.c deleted file mode 100644 index 9de156a..0000000 --- a/controller.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "pipewire/keys.h" -#include "pipewire/port.h" -#include "spa/pod/iter.h" -#include "spa/utils/defs.h" -#include <signal.h> -#include <stdio.h> - -#include <spa/control/control.h> -#include <spa/param/latency-utils.h> -#include <spa/pod/builder.h> -#include <spa/pod/pod.h> - -#include <pipewire/filter.h> -#include <pipewire/pipewire.h> - -#include "delay.h" -#include "gate.h" -#include "guitfx.h" -#include "sust.h" - -void midi_control( - struct FxData* data, - - uint64_t frame, - uint64_t offset, - unsigned sec, - unsigned midi_size, - uint8_t* midi_data, - struct spa_io_position* position) -{ - printf("[%d] MIDI message (%d bytes) : %x, %x, %x\n", sec, midi_size, - midi_data[0], midi_data[1], midi_data[2]); - - switch (midi_data[0] & 0xff) { - case 0xb0: - switch (midi_data[1]) { - case 0x0b: - // expr pedal - float val_f = ((float)midi_data[2]) / 128.0; - - float thres = 0.5; - - if (val_f > thres) { - float expr_mix = (val_f - thres) / (1.0 - thres); - printf("Expr Pedal %f\n", expr_mix); - - data->delay.mix = expr_mix; - } else { - data->delay.mix = 0.0; - } - break; - - case 0x42: - - // noise gate calibration - if (data->prog == 2) { - if (midi_data[2] >= 64) { - data->gate.threshold = data->gate.cur_block_sum * 0.8; - printf("calibrate noise gate: threshold = %f\n", - data->gate.threshold); - } - } - - // sust pedal - if (data->prog == 1) { - if (midi_data[2] >= 64) { - sust_swap(&data->sust); - data->sust.playing = true; - - data->sust.start_idx = data->sust.idx; - data->sust.idx = 0; - } else { - data->sust.playing = false; - } - } - - // tap tempo - if (data->prog == 0) { - uint64_t cur_tap = frame + offset; - uint64_t duration = cur_tap - data->last_tap; - data->last_tap = cur_tap; - if (duration < (4 * position->clock.rate.denom)) { - delay_set_time(&data->delay, duration); - } - - sust_resize(&data->sust, duration); - } - - break; - } - - break; - - case 0xc0: - // program change - if (midi_data[2] >= 64) { - sust_swap(&data->sust); - data->sust.playing = true; - - data->sust.start_idx = data->sust.idx; - data->sust.idx = 0; - } else { - data->sust.playing = false; - } - printf("program change: %u\n", midi_data[1]); - data->prog = midi_data[1]; - break; - } -} diff --git a/delay.c b/delay.c index 1723ca9..31f3089 100644 --- a/delay.c +++ b/delay.c @@ -1,12 +1,12 @@ -#include "delay.h" -#include <stddef.h> #include <stdint.h> -#include <stdio.h> +#include <stddef.h> #include <stdlib.h> +#include <stdio.h> +#include "delay.h" void delay_init( - struct delay* delay) -{ + struct delay * delay +) { delay->mix = 0.8; delay->feedback = 0.8; delay->duration = 0; @@ -16,38 +16,39 @@ void delay_init( } void delay_set_time( - struct delay* delay, - uint64_t new_duration) -{ + struct delay * delay, + uint64_t new_duration +) { printf("set delay duration to %lu samples\n", new_duration); - if (new_duration > delay->buf_capacity) { + if( new_duration > delay->buf_capacity ) { delay->buf_capacity = new_duration; - delay->buf = realloc(delay->buf, sizeof(float) * new_duration); + delay->buf = realloc( delay->buf, sizeof(float) * new_duration ); } - for (int i = delay->duration; i < new_duration; ++i) { + for( int i = delay->duration; i < new_duration; ++i ) { delay->buf[i] = delay->buf[i - delay->duration]; } delay->duration = new_duration; - if (new_duration > 0) { + if( new_duration > 0 ) { delay->buf_idx %= new_duration; } } void delay_process( - struct delay* delay, + struct delay * delay, size_t frame_size, - float const* in, - float* out) -{ - for (size_t i = 0; i < frame_size; ++i) { - if (delay->duration > 0) { - out[i] = in[i] - + delay->mix * delay->buf[delay->buf_idx]; + float const * in, + float * out +) { + for( size_t i = 0; i < frame_size; ++i ) { + if( delay->duration > 0 ) { + out[i] = + in[i] + + delay->mix * delay->buf[ delay->buf_idx ]; - delay->buf[delay->buf_idx] *= delay->feedback; - delay->buf[delay->buf_idx] += (1.0 - delay->feedback) * in[i]; + delay->buf[ delay->buf_idx ] *= delay->feedback; + delay->buf[ delay->buf_idx ] += (1.0 - delay->feedback) * in[i]; delay->buf_idx = (delay->buf_idx + 1) % delay->duration; } else { out[i] = 0.5 * in[i]; diff --git a/delay.h b/delay.h index 499b1cc..4ed2cf5 100644 --- a/delay.h +++ b/delay.h @@ -1,7 +1,7 @@ #pragma once -#include <stddef.h> #include <stdint.h> +#include <stddef.h> struct delay { uint64_t duration; @@ -10,18 +10,21 @@ struct delay { uint64_t buf_idx; size_t buf_capacity; - float* buf; + float * buf; }; void delay_init( - struct delay* delay); + struct delay * delay +); void delay_set_time( - struct delay* delay, - uint64_t new_duration); + struct delay * delay, + uint64_t new_duration +); void delay_process( - struct delay* delay, + struct delay * delay, size_t frame_size, - float const* in, - float* out); + float const * in, + float * out +); diff --git a/gate.c b/gate.c deleted file mode 100644 index 3f13c6a..0000000 --- a/gate.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "gate.h" -#include <math.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> - -void gate_init( - struct gate* gate) -{ - gate->threshold = 0.0; - gate->enable_calibration = false; - - gate->block_size = 1024; - gate->cur_block_count = 0; - gate->cur_block_sum = 0.0; - - gate->is_active = false; - gate->cur_gain = 1.0; - gate->attack = 1.0 / 128.0; - gate->release = 1.0 / 8192.0; -} - -void gate_process( - struct gate* gate, - size_t frame_size, - float const* in, - float* out) -{ - - bool act = false; - - for (size_t i = 0; i < frame_size; ++i) { - gate->cur_block_sum += fabs(in[i]); - gate->cur_block_count += 1; - - if (gate->cur_block_count >= gate->block_size) { - // printf("new block sum %f, gain = %f\n", gate->cur_block_sum, gate->cur_gain); - - gate->last_block_sum = gate->cur_block_sum; - gate->cur_block_sum = 0.0; - - if (gate->last_block_sum > 0.03) { - act = true; - } else { - act = false; - } - } - - if (act) { - gate->cur_gain += gate->attack; - if (gate->cur_gain > 1.0) { - gate->cur_gain = 1.0; - } - } else { - gate->cur_gain -= gate->release; - if (gate->cur_gain < 0.0) { - gate->cur_gain = 0.0; - } - } - - out[i] = in[i] * gate->cur_gain; - } -} diff --git a/gate.h b/gate.h deleted file mode 100644 index 3773e5c..0000000 --- a/gate.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -struct gate { - float threshold; - bool enable_calibration; - - unsigned block_size; - unsigned cur_block_count; - float cur_block_sum; - float last_block_sum; - - bool is_active; - float cur_gain; - - float attack; - float release; -}; - -void gate_init(); -void gate_process( - struct gate* gate, - size_t frame_size, - float const* in, - float* out); diff --git a/guitfx.c b/guitfx.c index f9afddd..052e37a 100644 --- a/guitfx.c +++ b/guitfx.c @@ -2,184 +2,255 @@ #include "pipewire/port.h" #include "spa/pod/iter.h" #include "spa/utils/defs.h" -#include <signal.h> #include <stdio.h> +#include <signal.h> +#include <spa/pod/pod.h> +#include <spa/pod/builder.h> #include <spa/control/control.h> #include <spa/param/latency-utils.h> -#include <spa/pod/builder.h> -#include <spa/pod/pod.h> -#include <pipewire/filter.h> #include <pipewire/pipewire.h> +#include <pipewire/filter.h> #include "delay.h" -#include "gate.h" -#include "guitfx.h" #include "sust.h" -float envelope(float x); - +float envelope( float x ); struct data; struct port { - struct data* data; + struct data *data; }; -void midi_control( - struct FxData* data, - - uint64_t frame, - uint64_t offset, - unsigned sec, - unsigned midi_size, - uint8_t* midi_data, - struct spa_io_position* position); - struct data { - struct pw_main_loop* loop; - struct pw_filter* filter; - struct port* guit_in_port; - struct port* midi_in_port; - struct port* out_port; - struct FxData fx_data; + struct pw_main_loop * loop; + struct pw_filter * filter; + struct port * guit_in_port; + struct port * midi_in_port; + struct port * out_port; + + //! effect data + uint64_t last_tap; + struct delay delay; + struct sust sust; + + unsigned prog; + + //! elapsed time in number of samples + uint64_t time; }; -static void on_process(void* userdata, struct spa_io_position* position) +static void on_process(void *userdata, struct spa_io_position *position) { - struct data* data = userdata; + struct data *data = userdata; - uint32_t n_samples = position->clock.duration; - uint64_t frame = data->fx_data.time; - data->fx_data.time += n_samples; + uint32_t n_samples = position->clock.duration; + uint64_t frame = data->time; + data->time += n_samples; - struct pw_buffer* b = pw_filter_dequeue_buffer(data->midi_in_port); - if (b == NULL) { - fprintf(stderr, "on_process(): no buffer for midi_in_port\n"); - return; - } + struct pw_buffer * b = pw_filter_dequeue_buffer(data->midi_in_port); + if( b == NULL ) { + fprintf(stderr, "on_process(): no buffer for midi_in_port\n"); + return; + } - struct spa_buffer* buf = b->buffer; - spa_assert(buf->n_datas == 1); - struct spa_data* d = &buf->datas[0]; + struct spa_buffer * buf = b->buffer; + spa_assert(buf->n_datas == 1); + struct spa_data * d = &buf->datas[0]; - if (d->data) { - struct spa_pod* pod = spa_pod_from_data(d->data, d->maxsize, - d->chunk->offset, d->chunk->size); + if( d->data ) { + struct spa_pod * pod = + spa_pod_from_data( + d->data, + d->maxsize, + d->chunk->offset, + d->chunk->size + ); - if (pod) { - if (spa_pod_is_sequence(pod)) { - struct spa_pod_sequence* pod_seq = (struct spa_pod_sequence*)pod; - struct spa_pod_control* c; - SPA_POD_SEQUENCE_FOREACH(pod_seq, c) - { - if (c->type == SPA_CONTROL_Midi) { - unsigned sec = (frame + c->offset) / (float)position->clock.rate.denom; - char* midi_data = SPA_POD_BODY(&c->value); - unsigned midi_size = SPA_POD_BODY_SIZE(&c->value); + if( pod ) { + if( spa_pod_is_sequence(pod) ) { + struct spa_pod_sequence * pod_seq = (struct spa_pod_sequence*) pod; + struct spa_pod_control * c; + SPA_POD_SEQUENCE_FOREACH(pod_seq, c) { + if( c->type == SPA_CONTROL_Midi ) { + unsigned sec = + (frame + c->offset) + / (float) position->clock.rate.denom; + char * midi_data = SPA_POD_BODY(&c->value); + unsigned size = SPA_POD_BODY_SIZE(&c->value); - midi_control(&data->fx_data, frame, c->offset, sec, midi_size, midi_data, position); - } else { - printf("on_process(): non midi-control\n"); - } - } - } else { - fprintf(stderr, "on_process(): unexpected POD that is not a sequence " - "(midi_in_port)\n"); - } - } else { - fprintf(stderr, "on_process(): pod is NULL\n"); - } - } else { - fprintf(stderr, "on_process(): no data in buffer of midi_in_port\n"); - } + printf("[%d] MIDI message (%d bytes) : %x, %x, %x\n", sec, size, midi_data[0], midi_data[1], midi_data[2]); - pw_filter_queue_buffer(data->midi_in_port, b); + switch( midi_data[0] & 0xff ) { + case 0xb0: + switch( midi_data[1] ) { + case 0x0b: + // expr pedal + float val_f = ((float)midi_data[2]) / 128.0; + printf("Expr Pedal %f\n", val_f); + if ( val_f > 0.1 ) { + data->delay.mix = val_f; + } else { + data->delay.mix = 0.0; + } + break; - float* const in = pw_filter_get_dsp_buffer(data->guit_in_port, n_samples); - float tmp1[n_samples]; - float tmp2[n_samples]; - float* out = pw_filter_get_dsp_buffer(data->out_port, n_samples); - if (in && out) { - gate_process(&data->fx_data.gate, n_samples, in, tmp1); - sust_process(&data->fx_data.sust, n_samples, tmp1, tmp2); - delay_process(&data->fx_data.delay, n_samples, tmp2, out); - } + case 0x42: + // sust pedal + if( data->prog == 1 ) { + if( midi_data[2] >= 64) { + sust_swap( &data->sust ); + data->sust.playing = true; + + data->sust.start_idx = data->sust.idx; + data->sust.idx = 0; + } else { + data->sust.playing = false; + } + } + + // tap tempo + if( data->prog == 0 ) { + uint64_t cur_tap = frame + c->offset; + uint64_t duration = cur_tap - data->last_tap; + data->last_tap = cur_tap; + if( duration < (4*position->clock.rate.denom) ) { + delay_set_time( &data->delay, duration ); + } + + + sust_resize( &data->sust, duration ); + } + + break; + } + + break; + + case 0xc0: + // program change + printf("program change: %u\n", midi_data[1]); + data->prog = midi_data[1]; + break; + } + } else { + printf("on_process(): non midi-control\n"); + } + } + } else { + fprintf(stderr, "on_process(): unexpected POD that is not a sequence (midi_in_port)\n"); + } + } else { + fprintf(stderr, "on_process(): pod is NULL\n"); + } + } else { + fprintf(stderr, "on_process(): no data in buffer of midi_in_port\n"); + } + + pw_filter_queue_buffer(data->midi_in_port, b); + + + float * const in = pw_filter_get_dsp_buffer(data->guit_in_port, n_samples); + float tmp[n_samples]; + float * out = pw_filter_get_dsp_buffer(data->out_port, n_samples); + if( in && out ) { + sust_process( &data->sust, n_samples, in, tmp ); + delay_process( &data->delay, n_samples, tmp, out ); + } } static const struct pw_filter_events filter_events = { - PW_VERSION_FILTER_EVENTS, - .process = on_process, + PW_VERSION_FILTER_EVENTS, + .process = on_process, }; -static void do_quit(void* userdata, int signal_number) +static void do_quit(void *userdata, int signal_number) { - struct data* data = userdata; - pw_main_loop_quit(data->loop); + struct data *data = userdata; + pw_main_loop_quit(data->loop); } -int main(int argc, char* argv[]) +int main(int argc, char *argv[]) { - struct data data = { - 0, - }; + struct data data = { 0, }; - gate_init(&data.fx_data.gate); - delay_init(&data.fx_data.delay); - sust_init(&data.fx_data.sust); - data.fx_data.prog = 0; + delay_init( &data.delay ); + sust_init( &data.sust ); + data.prog = 0; - const struct spa_pod* params[1]; - uint8_t buffer[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + const struct spa_pod *params[1]; + uint8_t buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); - pw_init(&argc, &argv); + pw_init(&argc, &argv); - data.loop = pw_main_loop_new(NULL); + data.loop = pw_main_loop_new(NULL); - pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGINT, do_quit, &data); - pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGTERM, do_quit, &data); + pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGINT, do_quit, &data); + pw_loop_add_signal(pw_main_loop_get_loop(data.loop), SIGTERM, do_quit, &data); - data.filter = pw_filter_new_simple( - pw_main_loop_get_loop(data.loop), "Guitar FX", - pw_properties_new(PW_KEY_MEDIA_TYPE, "Audio", PW_KEY_MEDIA_CATEGORY, - "Filter", PW_KEY_MEDIA_ROLE, "DSP", NULL), - &filter_events, &data); + data.filter = pw_filter_new_simple( + pw_main_loop_get_loop(data.loop), + "Guitar FX", + pw_properties_new( + PW_KEY_MEDIA_TYPE, "Audio", + PW_KEY_MEDIA_CATEGORY, "Filter", + PW_KEY_MEDIA_ROLE, "DSP", + NULL), + &filter_events, + &data); - data.midi_in_port = pw_filter_add_port(data.filter, PW_DIRECTION_INPUT, - PW_FILTER_PORT_FLAG_MAP_BUFFERS, sizeof(struct port), - pw_properties_new(PW_KEY_FORMAT_DSP, "8 bit raw midi", - PW_KEY_PORT_NAME, "midi in", NULL), - NULL, 0); + data.midi_in_port = pw_filter_add_port(data.filter, + PW_DIRECTION_INPUT, + PW_FILTER_PORT_FLAG_MAP_BUFFERS, + sizeof(struct port), + pw_properties_new( + PW_KEY_FORMAT_DSP, "8 bit raw midi", + PW_KEY_PORT_NAME, "midi in", + NULL + ), + NULL, 0 + ); - data.guit_in_port = pw_filter_add_port( - data.filter, PW_DIRECTION_INPUT, PW_FILTER_PORT_FLAG_MAP_BUFFERS, - sizeof(struct port), - pw_properties_new(PW_KEY_FORMAT_DSP, "32 bit float mono audio", - PW_KEY_PORT_NAME, "guitar in", NULL), - NULL, 0); + data.guit_in_port = pw_filter_add_port(data.filter, + PW_DIRECTION_INPUT, + PW_FILTER_PORT_FLAG_MAP_BUFFERS, + sizeof(struct port), + pw_properties_new( + PW_KEY_FORMAT_DSP, "32 bit float mono audio", + PW_KEY_PORT_NAME, "guitar in", + NULL), + NULL, 0); - data.out_port = pw_filter_add_port( - data.filter, PW_DIRECTION_OUTPUT, PW_FILTER_PORT_FLAG_MAP_BUFFERS, - sizeof(struct port), - pw_properties_new(PW_KEY_FORMAT_DSP, "32 bit float mono audio", - PW_KEY_PORT_NAME, "fx out", NULL), - NULL, 0); + data.out_port = pw_filter_add_port(data.filter, + PW_DIRECTION_OUTPUT, + PW_FILTER_PORT_FLAG_MAP_BUFFERS, + sizeof(struct port), + pw_properties_new( + PW_KEY_FORMAT_DSP, "32 bit float mono audio", + PW_KEY_PORT_NAME, "fx out", + NULL), + NULL, 0); - params[0] = spa_process_latency_build( - &b, SPA_PARAM_ProcessLatency, - &SPA_PROCESS_LATENCY_INFO_INIT(.ns = 10 * SPA_NSEC_PER_MSEC)); + params[0] = spa_process_latency_build(&b, + SPA_PARAM_ProcessLatency, + &SPA_PROCESS_LATENCY_INFO_INIT( + .ns = 10 * SPA_NSEC_PER_MSEC + )); - if (pw_filter_connect(data.filter, PW_FILTER_FLAG_RT_PROCESS, params, 1) < 0) { - fprintf(stderr, "can't connect\n"); - return -1; - } + if (pw_filter_connect(data.filter, + PW_FILTER_FLAG_RT_PROCESS, + params, 1) < 0) { + fprintf(stderr, "can't connect\n"); + return -1; + } - pw_main_loop_run(data.loop); + pw_main_loop_run(data.loop); - pw_filter_destroy(data.filter); - pw_main_loop_destroy(data.loop); - pw_deinit(); + pw_filter_destroy(data.filter); + pw_main_loop_destroy(data.loop); + pw_deinit(); - return 0; + return 0; } diff --git a/guitfx.h b/guitfx.h deleted file mode 100644 index 8c3cb7e..0000000 --- a/guitfx.h +++ /dev/null @@ -1,16 +0,0 @@ - -#include "delay.h" -#include "gate.h" -#include "sust.h" - -struct FxData { - uint64_t last_tap; - struct delay delay; - struct sust sust; - struct gate gate; - - unsigned prog; - - //! elapsed time in number of samples - uint64_t time; -}; diff --git a/meson.build b/meson.build index ab53a04..9fc0dd8 100644 --- a/meson.build +++ b/meson.build @@ -9,7 +9,5 @@ executable( 'guitfx.c', 'delay.c', 'sust.c', - 'gate.c', - 'controller.c', dependencies : [pipewire_dep, m_dep], ) diff --git a/sust.c b/sust.c index f9d31a2..d684930 100644 --- a/sust.c +++ b/sust.c @@ -1,10 +1,9 @@ #include "sust.h" #include <math.h> -#include <stdio.h> #include <stdlib.h> +#include <stdio.h> -void sust_init(struct sust* sust) -{ +void sust_init( struct sust * sust ) { sust->mode = MODE_Sostenuto; sust->playing = false; @@ -13,76 +12,73 @@ void sust_init(struct sust* sust) sust->idx = 0; sust->buf_len = 51200; - sust->record_buf = malloc(sizeof(float) * sust->buf_len); - sust->play_buf = malloc(sizeof(float) * sust->buf_len); + sust->record_buf = malloc( sizeof(float) * sust->buf_len ); + sust->play_buf = malloc( sizeof(float) * sust->buf_len ); } -float envelope(float x) -{ - if (x < 0.4) +float envelope( float x ) { + if( x < 0.4 ) return (x / 0.4) * (x / 0.4); - if (x < 0.6) + if( x < 0.6 ) return 1.0; - float v = 1.0 - ((x - 0.6) / 0.4); - return v * v; + float v = 1.0 - ((x - 0.6) / 0.4); + return v*v; } -float softcos(float x) -{ - return sin(x * (3.141 / 2.0)); +float softcos( float x ) { + return sin( x * (3.141 / 2.0) ); } -void sust_resize(struct sust* sust, size_t new_len) -{ - sust->buf_len = new_len; - sust->play_buf = realloc(sust->play_buf, sizeof(float) * new_len); - sust->record_buf = realloc(sust->record_buf, sizeof(float) * new_len); - sust->idx %= new_len; +void sust_resize( struct sust * sust, size_t new_len ) { + sust->buf_len = new_len; + sust->play_buf = realloc( sust->play_buf, sizeof(float) * new_len ); + sust->record_buf = realloc( sust->record_buf, sizeof(float) * new_len ); + sust->idx %= new_len; } void sust_swap( - struct sust* sust) -{ - float* tmp = sust->play_buf; + struct sust * sust +) { + float * tmp = sust->play_buf; sust->play_buf = sust->record_buf; sust->record_buf = tmp; - for (int i = 0; i < sust->buf_len; ++i) { + for( int i = 0; i < sust->buf_len; ++i ) { sust->record_buf[i] = sust->play_buf[i]; } } void sust_process( - struct sust* sust, + struct sust * sust, size_t frame_size, - float const* in, - float* out) -{ - for (size_t i = 0; i < frame_size; ++i) { + float const * in, + float * out +) { + for( size_t i = 0; i < frame_size; ++i ) { - if (sust->mode == MODE_Sustain && sust->idx == 0) { - sust_swap(sust); + if( sust->mode == MODE_Sustain && sust->idx == 0 ) { + sust_swap( sust ); } float out_value = in[i]; - if (sust->playing) { + if( sust->playing ) { int n_voices = 5; - for (int v = 0; v < n_voices; ++v) { - size_t play_idx = (sust->start_idx + sust->idx + ((v * sust->buf_len) / n_voices)) % sust->buf_len; - float gain = envelope(((float)play_idx) / ((float)sust->buf_len)); - // printf("gain = %f\n", gain); - out_value += 0.5 * gain * sust->play_buf[play_idx]; + for( int v = 0; v < n_voices; ++v ) { + size_t play_idx = (sust->start_idx + sust->idx + ((v*sust->buf_len)/n_voices)) % sust->buf_len; + float gain = envelope( ((float) play_idx) / ((float)sust->buf_len) ); + //printf("gain = %f\n", gain); + out_value += 0.5 *gain * sust->play_buf[ play_idx ]; } } - if (sust->mode == MODE_Sostenuto) { - sust->record_buf[sust->idx] = in[i]; + if( sust->mode == MODE_Sostenuto ) { + sust->record_buf[ sust->idx ] = in[i]; } - if (sust->mode == MODE_Sustain) { - sust->record_buf[sust->idx] = 0.5 * out_value; + if( sust->mode == MODE_Sustain ) { + sust->record_buf[ sust->idx ] = 0.5*out_value; } sust->idx = (sust->idx + 1) % sust->buf_len; diff --git a/sust.h b/sust.h index a0472b1..92bece8 100644 --- a/sust.h +++ b/sust.h @@ -15,16 +15,18 @@ struct sust { size_t start_idx; size_t idx; size_t buf_len; - float* record_buf; - float* play_buf; + float * record_buf; + float * play_buf; }; -void sust_init(struct sust* sust); -void sust_resize(struct sust* sust, size_t new_len); -void sust_swap(struct sust* sust); + +void sust_init( struct sust * sust ); +void sust_resize( struct sust * sust, size_t new_len ); +void sust_swap( struct sust * sust ); void sust_process( - struct sust* sust, + struct sust * sust, size_t frame_size, - float const* in, - float* out); + float const * in, + float * out +);