Browse Source

Initial commit

spesk 2 years ago
parent
commit
11fca77958
4 changed files with 303 additions and 0 deletions
  1. 32 0
      example.modmark
  2. 43 0
      example.module
  3. 27 0
      ideas.org
  4. 201 0
      pl_proto.pl

+ 32 - 0
example.modmark

@@ -0,0 +1,32 @@
+#lang reader modmark_br.rkt
+# Patch Spec
+# Representing an approximation of
+# a 909 kick. Module specs are imported
+# but don't yet exist
+
+Title: Kick Drum
+
+# By default "./modules" is included in the module path
+ModuleDir "/home/swatson/Repos/modular-markup/"
+
+import Module::BlueLantern::AsteroidOperatorVCF as VCF
+import Module::MakeNoise::Maths
+import Module::ALM::TangleQuartet as VCA
+import Module::Generic::Output
+
+set VCF.Pluck = on
+set VCF.Freq.position = 7
+
+set Maths.Cycle[1] = on
+set Maths.Rise[1].position = 7
+set Maths.Fall[1].position = 1
+set Maths.LogExp.position = 5
+
+set VCA.Input1.position = 5
+
+# Output of Maths env into VCF freq modulation
+connect Maths.1f VCF.PluckMod
+# Output of VCF into VCA
+connect VCF.Output.Overdrive VCA.Input1
+# VCA into soundcard/output
+connect VCA.Input1 Output.1

+ 43 - 0
example.module

@@ -0,0 +1,43 @@
+# Module Spec
+
+Manufacturer: MakeNoise
+Module: Maths
+Revision: null
+- Input: Slew1
+- Input: Slew2
+- Input: Trig1
+- Input: Trig2
+- Input: Attenuveter1
+-- Position: [7-12],[1-5]
+- Input: Attenuveter2
+-- Position: [7-12],[1-5]
+- Input: Attenuveter3
+-- Position: [7-12],[1-5]
+- Input: Attenuveter4
+-- Position: [7-12],[1-5]
+- Input: Rise1
+-- Position: [7-12],[1-5]
+- Input: Rise2
+-- Position: [7-12],[1-5]
+- Input: Both1
+- Input: Both2
+- Input: Fall1
+-- Position: [7-12],[1-5]
+- Input: Fall2
+-- Position: [7-12],[1-5]
+- Input: Cycle1
+- Input: Cycle2
+- Knob: LogExp
+-- Position: [7-12],[1-5]
+- Button: Cycle1
+- Button: Cycle2
+- Output: 1f
+- Output: 1
+- Output: 2
+- Output: 3
+- Output: 4
+- Output: 4f
+- Output: Or
+- Output: Sum
+- Output: Inv
+-- Position: [1-3]

+ 27 - 0
ideas.org

@@ -0,0 +1,27 @@
+
+Ideas for markup language that can describe modular patches.
+
+Ideally, output is a conceptual flow chart of patches. Additionally,
+patch construction can be done in an interactive shell, or via a patch file
+that provides intuituve shorthand for patch markup.
+
+Use cases:
+- random patch generation
+- patch "type checking"
+- brevity in expressing/sharing LARGE patches
+  - the trade off being you have to learn the language
+
+Idea is to place burden of patch notation on module notation, as opposed
+to connection notation. It's inconvinent to specific the module, but this can be
+community sourced and then should be trivially easy to do patch notation. See
+below example.
+
+
+
+Syntax would look something like:
+
+[[file:~/Repos/modular-markup/example.modmark][Kick Drum Example]]
+
+#+BEGIN_SRC lisp
+
+#+END_SRC

+ 201 - 0
pl_proto.pl

@@ -0,0 +1,201 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Data::Dumper;
+
+my $SOURCE_FILE = $ARGV[0];
+
+sub read_to_var($) {
+	my $file_path = shift;
+	my $content;
+	open(my $fh, '<', $file_path) or die "cannot open file $file_path";
+	{
+		local $/;
+		$content = <$fh>;
+	}
+	close($fh);
+
+	return $content;
+}
+
+my $src_content = read_to_var($SOURCE_FILE);
+
+sub trim($) {
+	my $str = shift;
+	$str =~ s/^\s+|\s+$//g;
+	return $str;
+}
+
+my @module_library_paths = (
+	".",
+);
+my %modules;
+
+sub parse_module_file {
+	my $src = shift;
+
+	my %module;
+
+
+	my $last_proc_type = "null";
+	my $last_input = "null";
+	my $last_output = "null";
+	foreach my $line ( split("\n", $src) ) {
+		chomp $line;
+		if ( $line =~ m/^#/ ) {
+			next;
+		}
+
+		if ( $line =~ m/^Manufacturer:(.*)/ ) {
+			my $manu = $1;
+			$manu = trim($manu);
+			$module{'Manufacturer'} = $manu;
+		}
+
+		if ( $line =~ m/^Module:(.*)/ ) {
+			my $mod = $1;
+			$mod = trim($mod);
+			$module{'Module'} = $mod;
+		}
+
+		if ( $line =~ m/^Revision:(.*)/ ) {
+			my $rev = $1;
+			$rev = trim($rev);
+			$module{'Rev'} = $rev;
+		}
+
+		if ( $line =~ m/^-\ / ) {
+			if ( $line =~ m/^-\ Input:(.*)/ ) {
+				my $input = $1;
+				$input = trim($input);
+				my %input_chars;
+				$last_input = $input;
+				$last_proc_type = "input";
+				$module{'Inputs'}->{$input} = \%input_chars;
+			}
+
+			if ( $line =~ m/^-\ Knob:(.*)/ ) {
+				my $knob = $1;
+				$knob = trim($knob);
+				my %knob_chars;
+				$last_input = $knob;
+				$last_proc_type = "input";
+				$module{'Inputs'}->{$knob} = \%knob_chars;
+			}
+
+			if ( $line =~ m/^-\ Output:(.*)/ ) {
+				my $output = $1;
+				$output = trim($output);
+				my %output_chars;
+				$last_output = $output;
+				$last_proc_type = "output";
+				$module{'Outputs'}->{$output} = \%output_chars;
+			}
+		}
+
+		if ( $line =~ m/^--\ / ) {
+			if ( $line =~ m/^--\ Position:(.*)/ ) {
+				my $pos_args = $1;
+				$pos_args = trim($pos_args);
+				if ( $last_proc_type eq "input" ) {
+					$module{'Inputs'}->{$last_input}->{'pos'} = $pos_args;
+				} elsif ( $last_proc_type eq "output" ) {
+					$module{'Outputs'}->{$last_output}->{'pos'} = $pos_args;
+				}
+			}
+		}
+
+	}
+
+	return \%module;
+}
+
+my %AST;
+
+my %PARSE_TABLE = (
+	'comment' => '^#.*$',
+	'title' => '^Title: (.*)$',
+	'mod_path' => '^ModuleDir\ "(.*)"$',
+	'import' => '^import (Module)::([a-zA-Z0-9]{1,})::([a-zA-Z0-9]{1,})(.*$)',
+	'set' => '^set\ (.*)$',	    
+);
+
+my %PARSE_RULES = (
+	'comment' => sub {},
+	'title' => sub {
+		my $title = shift;
+		$AST{'Title'} = $title;
+	},
+	'mod_path' => sub {
+		my $file_path = shift;
+		if ( ! -d $file_path ) {
+			die "Path: $file_path doesn't look like a directory, exiting";
+		}
+
+		push(@module_library_paths, $file_path);
+	},
+	'import' => sub {
+		my $module_path = shift;
+		my @module_files = sub {
+			my @files;
+			foreach my $path ( @module_library_paths ) {
+				my @f = split("\n", `find $path`);
+				foreach my $file ( @f ) {
+					if ( $file =~ m/.module$/ ) {
+						push(@files, $file);
+					}
+				}
+			}
+			return @files;
+		}->();
+		foreach my $mod_file ( @module_files ) {
+			my $mod_file_content = read_to_var($mod_file);
+			my $mod_ref = parse_module_file($mod_file_content);
+
+			foreach my $ref ( @{$AST{'Modules'}} ) {
+				if ( $$mod_ref{'Manufacturer'} eq $$ref{'Manufacturer'} &&
+				     $$mod_ref{'Rev'} eq $$ref{'Rev'} ) {
+					# We've already imported this module
+					next;
+				} else {
+					push(@{$AST{'Modules'}}, $mod_ref);
+				}
+			}
+		}
+	},
+	'set' => sub { print("$_[0]\n"); },
+);
+
+# Basic line parser
+sub line_parse($) {
+	my $line = shift;
+	my $line_type = "null";
+	my @line_caps;
+	foreach my $key ( keys %PARSE_TABLE ) {
+		if ( $line =~ m/$PARSE_TABLE{$key}/ ) {
+			$line_type = $key;
+		}
+	}
+
+	if ( $line_type ne "null" && $line =~ m/$PARSE_TABLE{$line_type}/) {
+		if ( defined $1 ) {
+			$PARSE_RULES{$line_type}->($1);
+		} else {
+			$PARSE_RULES{$line_type}->();
+		}
+	} else {
+		print("$line\n");
+	}
+}
+
+foreach my $line ( split("\n", $src_content) ) {
+	chomp $line;
+	if ( $line eq "" ) {
+		next;
+	}
+	line_parse($line);
+}
+
+
+print Dumper %AST;