Mono source DX-7

I love the Yamaha DX-7 clone… and so I decided to make a few changes, and turn it into a single page of source code.

It extends the maximum limit for https://sccode.org, so instead it’s forked from the origin.

It’s extremely well done, with handcrafted formulas replicating every one of 16384 presets from the original & iconic breakthrough instrument based upon digital synthesis.

1 Like

This is great. Why not make it a class and a quark? It wouldn’t be too much more work, I don’t think.

Sam

i am using a self made adaption of this DX7 clone for use with LNX Studio, and I was wondering how to share it. it currently offers only a very rudimentary interface, with two knobs for 128 banks of 128 sounds each, but its excellent when played with a velocity sensitive keyboard thanks to the large number of presets provided.

It’s an excellent idea Sam.

With the included license at the end of the source page, it’s free to Do what thou wilt

There’s one caveat I couldn’t improve from the original source.

The main function defines a new ParGroup as a local var… so hitting Cmd. will cause this to occur:

FAILURE IN SERVER /n_free Node 1009 not found
FAILURE IN SERVER /n_set Node 1004 not found
FAILURE IN SERVER /s_new Group 1003 not found

I tried one solution:

  • changing the local var to global
  • appending the source with CmdPeriod.add{ ~dx7group = new ( ParGroup ) }

Of course, the synthdefs are compiled & defined with the original group object which the global (or local) variable is simply a reference to… which means once the group is freed, there’s no way to get it back.

Some workarounds:

  • setting CmdPeriod.freeServers to false to disable s.freeAll from CmdPeriod.objects, though should be left to the user
  • wrapping the entire source inside of CmdPeriod.add, which beyond being rather unelegant would require the interpreter variables to be redeclared since the source function is so large to the extent it only works when used directly with the interpreter.

So ultimately I believe this task may be rather unelegant & daunting unless there’s a determined path to turn this ParGroup into a persistent one.

Perhaps a repository with a title referring to both projects with seamless conjunction.

Since both are home to the same platform, it’s sensible to release this where it may be discovered

…from a related search.

If it’s going to be a class, then you would want to make instances of the class. So the object constructor method would be responsible for preparing the group/bus architecture.

Then there are two ways:

  • Perhaps less user friendly: Cmd-dot destroys the instance and the user can recreate it. (This probably loses settings, so perhaps not ideal.)
  • Or: The instance registers with ServerTree to rebuild its architecture (groups, buses and all synths) automatically.

There’s nothing daunting about it tbh. This is one area where classes and instances are very good, and a freestanding block of code may not be good.

hjh

thanks. I was hoping to avoid creating another repo. Interesting input about where it could be better discovered, i’ll keep pondering if this is better submitted as a PR to possibly be with the original DX7 clone repo, somewhere else or a repo i’ll make if it is strictly necessary.

I only mentioned it in your thread because it is exactly that, a conversion of this code into a class. Granted it uses some of LNX framework, but not much of it is LNX specific. In terms of functionality it does the same thing, managing of buses and groups, and could be easily adapted to vanilla SC.

Excellent work @Herman… very well done.

I admit that based from everyone’s input, I don’t believe I have what it takes to refactor the Yamaha DX-7 clone into a solid class extension.

I can say for the benefit of anyone who would undertake such a task, refactoring the original DX-7 source code into a single page was actually very simple.

At the end of the main function, there is a single condensed file operation before returning to the original source code for mainCaller =

    File.use(thisProcess.nowExecutingPath, "r",
		{
			|file|

			file.seek(file.contents.findRegexp("/\\*\\*\\*")[0][0] + 5);

			16384.do({arg item;
				dx7patches[item] = file.getLine;
			});
		}
	);

	mainCaller = // ...

The original source uses interpreter variable this.l to hold the file data because like this.d in the mono source dx-7, the data is just too large to be used in any other way.