8 ms·
Tonal.js: Functional music theory lib
- dr_dshiv 3y agoHow is it different from tone.js?
- matteason 3y agoTone.js is a framework to actually play audio/music. Tonal.js deals with music theory but not actually turning that into audio
- hasty_pudding 3y ago"all functions are pure, there is no data mutation, and entities are represented by data structures instead of objects." God i love to see this
- recursive 3y agoIn javascript, what data structure can you implement without objects? Pretty much nothing. Even arrays are objects.
- metaxy2 3y agoThey're using objects, including arrays [1], so I think they would have been more precise to say that they're using objects and arrays as simple data structures rather than using OO features like inheritance and mutation. [1] https://github.com/tonaljs/tonal/blob/main/packages/chord/index.ts https://github.com/tonaljs/tonal/blob/main/packages/chord/in...
- pcthrowaway 3y agoThis is just semantics then. If you're implementing a linked list or a tree without a class (or at the very least a function that behaves like a class), it's going to be awkward and clumsy. Data-structures beyond what the standard lib gives you (string and array) are the main reason the addition of classes to JS was so helpful.
- eitacaraleo 3y agoUh… what? It’s quite the opposite; why would you need a class for linked lists and trees?
- hasty_pudding 3y agoYou definitely need generic node objects to define the nodes. You could have a completely stateless class/object that would manipulate those nodes and add them and remove them from the data structure.
- metaxy2 3y agoWell, in principle you could have the node objects be created with an object literal in an outside builder function, and the manipulation also be done by outside functions. That's how it's done in languages without OOP. The question is how far are you willing to go to avoid doing anything that looks like OOP.
- hasty_pudding 3y agoVery far
- recursive 3y agoTo provide an easy place to find the behaviors that are included with those data structures.
- kamov 3y agoThis isn't quite right, linked lists and trees in functional languages can be represented extremely succintly, i.e. data List a = Nil | Node a (List a) data Tree a = Leaf a | Node (Tree a) (Tree a) there is nothing stopping you from writing something like this in JS const list = { kind: 'node', val: 3, next: { kind: 'nil' } }; And then using a switch case to navigate the list/tree matching on the kind field.
- 3y ago
- hasty_pudding 3y agoWhat they mean is functions and data are separate, emulating a more functional paradigm and less mutable state. The functions are kept pure and the data is kept pure. As opposed to an object oriented programming style in which data and functions share the same object and create bug ridden state machines thats not as easy to reason about. Some further explanation about this: https://www.goodreads.com/quotes/702062-immutable-objects-are-simple-they-can-only-be-in-one https://www.goodreads.com/quotes/702062-immutable-objects-ar... a semi-nuanced discussion: https://www.reddit.com/r/scala/comments/ejwsp1/is_mutability_really_that_bad/ https://www.reddit.com/r/scala/comments/ejwsp1/is_mutability... you can just Google mutable state to find more info. separating your data structures and functions in many cases will make your code cleaner and more bug free.
- recursive 3y agoI'm well aware of the pros and cons of mutability. I object (hah!) to this novel new use of the word "object". The concept is well defined by the ECMAScript spec. Your first link's first sentence's first two words are "Immutable objects". No problem there. It doesn't conflate objects with mutability.
- hasty_pudding 3y agoyou know how unsufferable it is when people bog a conversation down with semantics instead of ideas. the point is obvious. Being that every single language on Earth uses objects for non-primitive data structures that should be inferrable to a reasonable person. a data structure in that context is clearly an ordered grouping of objects versus an unordered/loose grouping of objects.
- recursive 3y agoI mean some languages don't. I have ideas but I don't think I'm getting them through. Most of the problems functional proselytizers have with objects come from inheritance and mutability. Instance methods from classes don't seem to conflict with any of the functional tenets. As for mutability, I think it's good sometimes. Dates should have been immutable, but Maps are a good fit for mutation. Immutable maps might make sense too sometimes. But I find it difficult to communicate about any of this when fundamental terminology is used in novel ways.
- hasty_pudding 3y agoWhat languages on Earth implement non-primitive data structures without objects? I guess maybe low level c and assembly where you implement everything as bits in physical memory?
- recursive 3y agoIt's mostly a question of what the language considers to be an object. There's often a stack-/heap-allocated dichotomy. Some languages consider stack-allocated structs not to be objects. They have no reference identity. Assignment has copy semantics. C# is one such language.
- jarmitage 3y agoUsed in https://strudel.cc https://strudel.cc (TidalCycles' JavaScript version) Specifically https://strudel.cc/learn/tonal/ https://strudel.cc/learn/tonal/
- smrtinsert 3y agoWonderful. Wanted something like this forever. Glad it exists
- helpfulContrib 3y agoI wonder if there is a similar library in C++?
- diggan 3y agoI'm not aware of any, but you could probably compile it to WebAssembly with Emscripten and use it that way, the library seems fairly simple for something like that.
- helpfulContrib 3y ago[dead]
- duranduran 3y agoTonal is great! I use it extensively here: https://app.bars.ai https://app.bars.ai There are a few small areas where the library hiccups, like with bigger chords. I've been able to work around some of those things by reframing the chord as an inversion of N relative to the root of whatever scale I'm in. I haven't bothered to debug why it does that, but my little work around has been sufficient.
- CodeIsTheEnd 3y agoUnsolicited feedback because I clicked: - Don't require picking a composition name before getting started - Whatever scroll settings you have broke swipe to go back, and then when I tapped the back button I got stuck in an infinite loop between the home page and the create composition page
- duranduran 3y agoThanks for testing it out! You're the third person to give me that feedback on the composition name on launch. I'll delete that step. On back navigation, that's really bad bug! I'll repro it and fix. Thanks for finding that!
- unikeko 3y agothis initially confused me; you might not be aware, but "functional" is a bit overloaded term with regard to music theory, see: functional harmony
- eyelidlessness 3y agoI mean, if the README is representative, “functional” is also appropriate in terms of the programming paradigm.
- systoll 3y agoIt’s mostly about the programming paradigm. @tonaljs/key gives you some specifically functional info, but the vast bulk of it as useful for non-functional analysis – though it does assume 12-tone equal temperament.
- seanhunter 3y agoFor people who are not aware, "functional harmony" means the extended system of tonal harmony that you hear in basically almost all music apart from a very few exceptions (eg free atonality, serialism etc but there aren't many compared to the very large amount of functional harmony out there). It's "functional" because the chords in the harmony have the function of establishing key centres, moving towards and away from them, establishing transitions to remote key areas etc. One of the best technical books about functional harmony is "Structural Functions of Harmony" by Arnold Schoenberg[1], which is much shorter than his "Harmonielehre" but really packed with interesting detail about key and chord relationships. [1] Yes that Schoenberg but this isn't about serialism, it's about trying to explain all the harmony up to and including Mahler. Here is an online pdf of an early edition https://is.muni.cz/el/1421/podzim2007/VH_53/Schoenberg_Structural_Functions.pdf https://is.muni.cz/el/1421/podzim2007/VH_53/Schoenberg_Struc...
- mrweiner 3y agoSmall correction — almost all *western* music.
- hannibalekta 3y agoIm working on a music learning app to study jazz licks and this is exactly what I needed. Thanks!
- grimmdude 3y agoI love Tonal.js, have used it for many personal projects including https://github.com/grimmdude/MidiWriterJS https://github.com/grimmdude/MidiWriterJS
- demondemidi 3y agoSurprised it doesn’t account for tempering given it is so comprehensive.
- giraffe_lady 3y agoI don't think it matters at this abstraction layer? You reason about intervals, scales, chords etc the same regardless of the tuning system. That only matters for sound production, which this doesn't do. It definitely assumes you're on a 12-tone system so is really only useful within western european music theory. But that is usually what people mean when they say "music theory" anyway.
- hunter2_ 3y agoIt matters for just one tiny aspect of the library: Note.freq(), Note.fromFreq(), etc.
- zengid 3y agoyou might be interested in something like tune.js https://github.com/instrumentbible/tune.js https://github.com/instrumentbible/tune.js
- cushpush 3y agoCan I set the tuning to A=432Hz ?
- ysofunny 3y agoyes, it doesn't really matter at all for this kind of system you can set it to zero, to negative one... possibly to the imaginary constant because this library does not actually make any sound. it's (to me) an implementation of 12tet, the standard western scale system which includes a bunch of scales and approximates the rest 'well' enough
- hunter2_ 3y agoI don't mean to lose my 'temper' here, but I think gp is hoping Note.freq(), Note.fromFreq(), etc. aren't locked into A440 as the examples imply. While >99% of the library doesn't deal with this at all, it would be handy nonetheless. Unfortunately, it's currently hard coded: https://github.com/tonaljs/tonal/blob/main/packages%2Fpitch-note%2Findex.ts#L126 https://github.com/tonaljs/tonal/blob/main/packages%2Fpitch-... https://github.com/tonaljs/tonal/blob/main/packages%2Fmidi%2Findex.ts#L47 https://github.com/tonaljs/tonal/blob/main/packages%2Fmidi%2...
- altruios 3y agoImaginary constant... complex tuning here we come! The ideal tuning isn't 440hz, it's (440+42i)hz /s
- ysofunny 3y agoup there with negative probability frequencies
- selenography 3y agoIsn't that just 442Hz, except about 34.3μs early?
- altruios 3y ago
- Freedom2 3y agoThanks for this! I've recently been exploring how to write a SATB four part harmony for a given melody / bass line, this takes a decent chunk of the boilerplate out for me.
- BHSPitMonkey 3y agoSince we're all sharing, I've been using this recently to replace Teoria in an old project of mine (a simple PWA for Duolingo-style sight reading and ear training practice, with MIDI support): https://www.getprelude.net/ https://www.getprelude.net/
- kerneloops 3y agoSee also: Well-typed music does not sound wrong (experience report), Haskell 2017 https://dl.acm.org/doi/10.1145/3122955.3122964 https://dl.acm.org/doi/10.1145/3122955.3122964
- justAnotherHero 3y agoI am currently working on an app with React Native that helps users play along to songs and one of the features needed was displaying the various scales/modes on the fretboard so I basically built a mini library of my own to construct the note arrays. This will be a great example to see how the library has handled the same problem.
- xor10 3y agoThis sounds interesting, how's the project coming along, got any demos? Want something like this.
- lodovic 3y agoThis is really nice! I am writing a guitar neck explorer tool to learn the patterns on the guitar neck. As I progress, I need to implement a lot more music theory than I really want to, so I was already looking around for something to integrate. This library will come in very handy. Nice work!
- rsrsrs86 3y agoPiano is easier to see - there’s only one way to do it!
- iamsaitam 3y ago(shameless plug) If you're interested in something more focused on creating music with tools for generating melodies, chord progressions, drum beats, etc., check out PLAYA at https://github.com/ricardomatias/playa https://github.com/ricardomatias/playa
- matteason 3y agoThanks for posting this! I've been experimenting with adding generative ambient music to my white noise app Ambiphone [0] using tone.js, but I've just been using manually written progressions and motifs, so I'm really excited to try this out. Just a heads up that your example at https://observablehq.com/@ricardomatias/playa https://observablehq.com/@ricardomatias/playa doesn't seem to be working at the moment because of browser autoplay restrictions - the console errors that look relevant are: > An AudioContext was prevented from starting automatically. It must be created or resumed after a user gesture on the page. > The AudioContext is "suspended". Invoke Tone.start() from a user action to start the audio. [0] https://ambiph.one https://ambiph.one
- iamsaitam 3y agoThanks for the heads up about the observable notebook. I suggest also having a look at the test cases, there's plenty examples in there on how to use the library. Congratz on Ambiphone, I'm using it right now, it's a nice concept of creating your own ambient mix!
- cess11 3y agoLooks nice. For silly exploratory projects I've previously used p5.sound: https://p5js.org/reference/#/libraries/p5.sound https://p5js.org/reference/#/libraries/p5.sound
- jjarvis 3y agoMax/Msp supports node.js. This would be very useful in a max patch.
- beaugunderson 3y agoi love this library; i used it to write a pedal steel guitar visualizer: https://beaugunderson.com/pedal-steel/ https://beaugunderson.com/pedal-steel/ try highlight → scale degree colors or highlight → chord formula and put "1 3 5 7" in the chord formula box... then play with the pedal checkboxes to see how you can play that chord vertically, or more stylistically by using the pedal slides
- revskill 3y agoCan we create remix music with this ?