--- Log opened Thu Aug 07 00:00:11 2008 |
01:23 | | gnolam [lenin@Nightstar-2037.A163.cust.bahnhof.se] has quit [Quit: Z?] |
01:24 | | Derakon[AFK] is now known as Derakon |
01:59 | | Thaqui [~Thaqui@Nightstar-13764.jetstream.xtra.co.nz] has joined #code |
01:59 | | mode/#code [+o Thaqui] by ChanServ |
02:01 | | Vornicus-Latens is now known as Vornicus |
02:32 | | Consul [~darren@Nightstar-1916.dsl.sfldmi.ameritech.net] has quit [Quit: Ex-Chat] |
02:57 | | Consul [~darren@Nightstar-1916.dsl.sfldmi.ameritech.net] has joined #code |
03:14 | | Derakon is now known as Derakon[AFK] |
03:26 | | Derakon[AFK] is now known as Derakon |
03:30 | | Attilla [~The.Attil@92.9.150.ns-26889] has quit [Ping Timeout] |
03:38 | | Attilla [~The.Attil@92.8.104.ns-27184] has joined #code |
03:38 | | mode/#code [+o Attilla] by ChanServ |
03:43 | | Reiv [~reaverta@Admin.Nightstar.Net] has joined #Code |
03:44 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Local kill by Reiv (Ghostbusting.)] |
03:44 | | Reiv is now known as Reiver |
04:07 | | Shoukanjuu [~Shoukanju@Nightstar-27098.101.8.67.cfl.res.rr.com] has quit [Connection reset by peer] |
04:10 | | Shoukanjuu [~Shoukanju@Nightstar-27098.101.8.67.cfl.res.rr.com] has joined #code |
05:12 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
05:14 | | Reiver [~reaverta@Nightstar-6941.xdsl.xnet.co.nz] has joined #Code |
05:14 | | mode/#code [+o Reiver] by ChanServ |
05:30 | | Kazriko [~kaz@Nightstar-26352.gdj-co.client.bresnan.net] has quit [Connection reset by peer] |
05:46 | | Kazriko [~kaz@Nightstar-26352.gdj-co.client.bresnan.net] has joined #code |
05:46 | | mode/#code [+o Kazriko] by ChanServ |
06:03 | | Reiv [~reaverta@Nightstar-6941.xdsl.xnet.co.nz] has joined #Code |
06:03 | | Reiver [~reaverta@Nightstar-6941.xdsl.xnet.co.nz] has quit [Ping Timeout] |
06:21 | | AnnoDomini [AnnoDomini@Nightstar-28960.neoplus.adsl.tpnet.pl] has joined #Code |
06:21 | | mode/#code [+o AnnoDomini] by ChanServ |
06:45 | | Derakon is now known as Derakon[AFK] |
07:17 | | Reiv [~reaverta@Nightstar-6941.xdsl.xnet.co.nz] has quit [Ping Timeout] |
07:24 | | Reiver [~reaverta@Nightstar-6941.xdsl.xnet.co.nz] has joined #Code |
07:24 | | mode/#code [+o Reiver] by ChanServ |
09:15 | | Thaqui [~Thaqui@Nightstar-13764.jetstream.xtra.co.nz] has quit [Quit: MORE constitution LESS destitution MORE pros...perity.] |
10:20 | | Thaqui [~Thaqui@Nightstar-13764.jetstream.xtra.co.nz] has joined #code |
10:20 | | mode/#code [+o Thaqui] by ChanServ |
10:29 | | gnolam [lenin@Nightstar-2037.A163.cust.bahnhof.se] has joined #Code |
10:29 | | mode/#code [+o gnolam] by ChanServ |
10:52 | | You're now known as TheWatcher |
11:35 | | Reiver [~reaverta@Nightstar-6941.xdsl.xnet.co.nz] has quit [Ping Timeout] |
12:11 | | Reiver [~reaverta@Nightstar-12317.xdsl.xnet.co.nz] has joined #Code |
12:11 | | mode/#code [+o Reiver] by ChanServ |
12:11 | | Reiver [~reaverta@Nightstar-12317.xdsl.xnet.co.nz] has quit [Client exited] |
12:11 | | Reiver [~reaverta@Admin.Nightstar.Net] has joined #Code |
12:11 | | mode/#code [+o Reiver] by ChanServ |
12:29 | | Attilla [~The.Attil@92.8.104.ns-27184] has quit [Quit: <Insert Humorous and/or serious exit message here>] |
12:37 | | Attilla [~The.Attil@92.8.104.ns-27184] has joined #code |
12:37 | | mode/#code [+o Attilla] by ChanServ |
12:42 | | Thaqui [~Thaqui@Nightstar-13764.jetstream.xtra.co.nz] has left #code [MORE constitution LESS destitution MORE pros...perity.] |
13:05 | | Reiv [~reaverta@Admin.Nightstar.Net] has joined #Code |
13:06 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
13:23 | | Reiv [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
13:24 | | Reiver [~reaverta@Admin.Nightstar.Net] has joined #Code |
13:24 | | mode/#code [+o Reiver] by ChanServ |
13:49 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
13:56 | | Reiver [~reaverta@Admin.Nightstar.Net] has joined #Code |
13:56 | | mode/#code [+o Reiver] by ChanServ |
14:15 | | gnolam [lenin@Nightstar-2037.A163.cust.bahnhof.se] has quit [Ping Timeout] |
14:54 | <@AnnoDomini> | jerith: This forum more to your liking? |
15:18 | | crem [~moo@Nightstar-28703.adsl.mgts.by] has quit [Ping Timeout] |
15:18 | | crem [~moo@Nightstar-28703.adsl.mgts.by] has joined #code |
15:20 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
15:27 | | gnolam [lenin@Nightstar-2037.A163.cust.bahnhof.se] has joined #Code |
15:27 | | mode/#code [+o gnolam] by ChanServ |
15:28 | | Reiver [~reaverta@Admin.Nightstar.Net] has joined #Code |
15:28 | | mode/#code [+o Reiver] by ChanServ |
18:38 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
18:45 | | Reiver [~reaverta@Admin.Nightstar.Net] has joined #Code |
18:45 | | mode/#code [+o Reiver] by ChanServ |
19:38 | < Consul> | Okay, a call for opinions, if I may... |
19:39 | < Consul> | I have a class, and part of the class is to store a collection of tags associated with a file. |
19:39 | | * AnnoDomini is watching the LP of Daikatana. |
19:39 | < Shoukanjuu> | Why. |
19:39 | < Shoukanjuu> | Why would you do such a thing? |
19:39 | < Consul> | Because I like tagging better than storing presets in banks. |
19:39 | < Shoukanjuu> | To AD, not you, Consul. You shouldn't listen to me about that kind of thing :P |
19:39 | < Consul> | Heh |
19:40 | < Consul> | Anyway, my question is... |
19:40 | < Consul> | How would you like the tag list returned to you from the object that contains it? |
19:40 | <@AnnoDomini> | It looks like a game tested only on one computer, with the monitor having a flaw of superfluous green component, so the user would crank down the green, and would report how the game looked to the designers, and they would make a game where there's fucking green everywhere. |
19:41 | < Consul> | Right now, I'm simply returning a semicolon-delimited string, on the basis that the programmer using said class can then parse it as he/she pleases. |
19:41 | < Consul> | However, I could design it to return an actual list object, if you folks feel that that would be better. |
19:41 | <@ToxicFrog> | Consul: I would like it returned as a list of tags |
19:42 | <@ToxicFrog> | It's easier to parse pure data because you don't need to parse it. |
19:42 | < Consul> | So, as a std::list then? |
19:42 | <@ToxicFrog> | And it's generally easier to turn an IR into a string than it is to do the converse. |
19:43 | <@ToxicFrog> | Much, much easier. |
19:43 | <@ToxicFrog> | Especially in C and C++, which fail at strings. |
19:43 | < Consul> | You need to be specific with me, as I see the word "list" bandied about in many different contexts when talking C++. |
19:43 | < Consul> | ToxicFrog: The problem is, each tag is a string. |
19:43 | < Consul> | No getting around that. |
19:44 | <@ToxicFrog> | So return a list - list being a std::list, a counted array, a linked list, whatever - of strings. |
19:44 | <@ToxicFrog> | Returning it as a string means: |
19:44 | < Consul> | Okay, I can live with that. |
19:44 | <@ToxicFrog> | (1) allocating a new string that holds it |
19:44 | <@ToxicFrog> | (2) copying all the tags into it, with extra happy fun time for delimiters |
19:44 | <@ToxicFrog> | (3) passing that to the caller, who must now do the whole thing in reverse to get the same data you started with in the first place. |
19:44 | < Consul> | Well, in the file format, the list of tags is stored as a semicolon-delimited string. |
19:45 | < Consul> | So the parsing has to happen regardless. |
19:45 | < Consul> | But I can keep it limited to within my class, so the user of said class has not to worry about it. |
19:46 | <@ToxicFrog> | That is generally a good idea. |
19:46 | <@ToxicFrog> | If you have a class that encapsulates some data, the users of it typically don't care how that data is stored on disk, nor should they need to - they want it in a format they can use. |
19:47 | < Consul> | Parameters are stored in a <string>,<string> map. but I have functions to return the proper data types for each perameter. |
19:48 | < Consul> | So you can go: float parameter = preset.getParam("param_name"); |
19:49 | < Consul> | And you don't have to care that it's stored as strings in class or on disk. |
19:49 | < Consul> | I question the efficiency of this approach, though, when one might be talking about hundreds or even thousands of parameters. |
19:50 | <@ToxicFrog> | What's the actual problem you're trying to solve here? |
19:50 | < Consul> | A preset storage and retrieval class for synths, samplers, and effects. |
19:50 | < Consul> | Software synths, samplers, effects that is/ |
19:51 | <@ToxicFrog> | Ok. And what are these "parameters"? |
19:51 | <@ToxicFrog> | keyvalue pairs? |
19:51 | < Consul> | Yup. key=>value |
19:51 | < Consul> | Well internally, they are. |
19:51 | < Consul> | In a synth, a parameter is a knob, basically, that effects the final sound output. |
19:52 | <@ToxicFrog> | Right. But fundamentally, each knob has a name - the key - and affects a value. |
19:52 | < Consul> | So, it's controller to value of controller mappings. |
19:52 | < Consul> | Yup/ |
19:52 | < Consul> | Stored in a text file. |
19:52 | < Consul> | And not bloody XML, either. |
19:52 | <@ToxicFrog> | So, the purpose of this class is to conveniently store and retrieve sets of KVs, where the keys are strings and the values are...floats? floats or strings? Any arbitrary data? |
19:53 | <@ToxicFrog> | Why not XML? |
19:54 | < Consul> | See, that's where it gets weird. |
19:54 | < Consul> | The parameter can be any kind of numeric value, but in a text file, it has to be stored as a string. |
19:54 | < Consul> | So, this class has function templates to convert from <type> to string and back. |
19:55 | <@ToxicFrog> | Forget about format for the moment. |
19:55 | < Consul> | That way, the type conversion is handled by the class, and not the calling program. |
19:55 | <@ToxicFrog> | The parameter is a real number, so in practical terms probably a double. |
19:55 | < Consul> | It could be a single, a double, an int, or a string, actually. |
19:55 | <@ToxicFrog> | So it can't be any kind of numeric value |
19:55 | < Consul> | Though probably never a string. |
19:55 | <@ToxicFrog> | It can be any kind of numeric value or string |
19:56 | < Consul> | Well, strings for things like the name of the preset, the name of the program the preset belongs to, and the like. |
19:56 | <@ToxicFrog> | What it's for is irrelevant. |
19:56 | <@ToxicFrog> | You need to have a clear idea of what data you are actually working with. |
19:57 | < Consul> | Oh dear, here we go again |
19:57 | < Consul> | I know what I'm dealing with. |
19:57 | < Consul> | The synth itself needs to use numbers to do synthesis. |
19:57 | <@ToxicFrog> | If you say "numbers" when you mean "numbers and strings", you're at best being confusing to everyone else, and at worst screwing yourself when you realize three classes later, shit, that needed to support strings as well, now I have to rewrite it. |
19:57 | < Consul> | So when the sound designer/synthesist goes to save his new preset, those numbers get written out to a text file. |
19:58 | < Consul> | Yes, we'll say that strings are required as well. |
19:58 | < Consul> | Because the metadata are strings. |
19:58 | <@ToxicFrog> | So, wait |
19:59 | <@ToxicFrog> | Metadata are parameters? |
19:59 | <@ToxicFrog> | Or each set of parameters has associated metadata? |
19:59 | < Consul> | I'm treating them as such. |
19:59 | < Consul> | Metadata are things like the preset's name, the name of the program the preset is for, the version number of that program, and the list of tags in semicolon-delimited form. |
19:59 | <@ToxicFrog> | What are the tags? |
20:00 | < Consul> | In fact, that's all the metadata. The rest are parameters belonging to the synth itself. |
20:00 | < Consul> | the tags are a list of strings. |
20:00 | <@ToxicFrog> | In the same sense as, say, blog tags? |
20:01 | < Consul> | Pretty much, yeah. It's a way people can organize their presets and sort/search them. |
20:01 | < Consul> | So, if I have a synth preset I designed for a movie score, I could put the project name as a tag. |
20:01 | <@ToxicFrog> | Right. Makes sense. |
20:02 | < Consul> | At least something I said finally does. :-P |
20:02 | <@ToxicFrog> | Ok, so question one: why not XML? There's lots of library support and this is more or less what it was designed for. And with thousands of params per preset, it's not going to be human editable anyways. |
20:02 | < Consul> | I looked up a variety of XML libs for C++ and couldn't figure out a single one. |
20:02 | < Consul> | If you know of one that lets me treat XML like a database or something like that, I'm all ears. |
20:03 | < Consul> | Creating a simple file format like: |
20:03 | < Consul> | parameter1:0.4859854563 |
20:03 | < Consul> | Makes it easy to store and reload. |
20:03 | < Consul> | Since a parameter is *always* a 1:1 mapping. |
20:04 | <@ToxicFrog> | Except that now you have to roll your own parser and generator for it. What if a parameter name contains a :, say? |
20:04 | < Consul> | The tags parameter is the only exception to that, and the one creating the challenge. |
20:04 | < Consul> | Simple: it throws an error, as a parameter is not allowed to have a : in it. |
20:04 | <@ToxicFrog> | Ok. |
20:04 | | * AnnoDomini mumbles. Doesn't know what the hell takes up so much space on C:. |
20:04 | < Consul> | Let's face it, that's not a serious limitation. |
20:05 | < Consul> | Shit!@ |
20:05 | <@ToxicFrog> | For tags, the quick and dirty approach: tags:<list of values>. The values are ; seperated. ; is not permitted in tags. |
20:05 | < Consul> | And then AnnoDomini mentions paths, and my entire format dies in front of my face. |
20:05 | <@ToxicFrog> | Whoops. |
20:05 | < Consul> | Because of paths to samples... |
20:05 | < Consul> | Well, maybe not. |
20:05 | < Consul> | Only on windows. |
20:05 | <@AnnoDomini> | 800 Mb of FOUND.000. ;_; |
20:05 | <@ToxicFrog> | And MacOS. |
20:05 | <@ToxicFrog> | And I think OSX still uses : as a path seperator, too. |
20:05 | < Consul> | okay, where's that easy to use XML library I need? |
20:06 | | * gnolam slaps ToxicFrog with the second 'a' in "separate". |
20:06 | <@ToxicFrog> | I actually don't know of one for C++, because I don't use C++. There's expat, but that's a tree-walking library, not DOM. |
20:06 | <@gnolam> | Or first. Whatever. |
20:06 | <@ToxicFrog> | You could just use Lua, it makes a good configuration language. |
20:06 | <@gnolam> | ToxicFrog: TinyXML? |
20:06 | <@ToxicFrog> | gnolam: ask him, not me |
20:07 | <@ToxicFrog> | You could also make use of the ASCII characters that exist for this very purpose - field seperator and record seperator |
20:07 | <@ToxicFrog> | they're nonprinting, so it's reasonable to have they constraint that they aren't permitted in names, tags, etc |
20:07 | < Consul> | I didn't know about those... |
20:07 | < Consul> | So much for that C++ class I took. |
20:09 | <@ToxicFrog> | They're not a C++ thing, they're an ASCII thing. |
20:09 | < Consul> | Most commercial softsynths just serialize their data into a binary format. |
20:09 | <@ToxicFrog> | And largely unused these days because stuff like XML exists. |
20:09 | <@ToxicFrog> | And machines are fast enough to make use of it. |
20:10 | <@ToxicFrog> | Anyways. My approach here would be to use Lua - it gives you a convenient scripting and configuration language and integrates nicely with C and C++. It's also fast, small, and portable. |
20:10 | <@ToxicFrog> | However, I'm horribly biased. |
20:11 | <@ToxicFrog> | And if you can find a library that exists specifically for storing arbitrary key/value pairs, that might be easier to use. |
20:11 | < Consul> | Well, the thing is, we're writing an entire suite of C++ header-only libs to make creating Linux softsynths and the like easier. |
20:11 | <@jerith> | .ini-style? |
20:12 | <@jerith> | [header] |
20:12 | <@jerith> | key=value |
20:12 | <@jerith> | foo=bar |
20:12 | <@jerith> | That kind of thing. |
20:12 | <@ToxicFrog> | There's always CDB: http://cr.yp.to/cdb.html |
20:12 | < Consul> | I have looked at Lua, and it could be fun to include as part of a larger sampler project. |
20:14 | < Consul> | At this point, I'm completely stuck. Maybe I should just make the presets themselves Lua scripts. |
20:14 | < Consul> | Which actually presents some intriguing possibilites from a sound design perspective. |
20:14 | < Consul> | Having full control logic as part of your preset... |
20:15 | < Consul> | Then I need a class that can act as a go-between between the C++ synth engine, and the preset file. |
20:16 | <@ToxicFrog> | That's not hard. |
20:16 | <@ToxicFrog> | If all you're using it for is KV storing as before, it's dead simple. |
20:16 | < Consul> | I need to think about this. |
20:17 | <@ToxicFrog> | Reading is one call for the initial load and perhaps 5-10 lines to read a value by key; writing is, again, 5-10 lines to store a value, and perhaps 40-50, tops, to save the file |
20:17 | <@ToxicFrog> | (all of which can be written in Lua, if you so choose) |
20:17 | < Consul> | The thing is, I like the idea of running a Lua script to load a preset. |
20:17 | < Consul> | The preset IS the script... |
20:17 | < Consul> | That would make scripting an integral part of the synth. |
20:17 | <@ToxicFrog> | Well, yes, that's how it would work when using it for storage |
20:18 | <@ToxicFrog> | You run the script and it creates the data structures which represent the preset |
20:18 | <@ToxicFrog> | The C++ part consists of code to access those structures conveinently |
20:18 | < Consul> | It would mean throwing away two weeks of off and on work... |
20:18 | <@ToxicFrog> | Are you perhaps thinking of the ability of the preset to run lua code while in use, not just at load time? |
20:18 | < Consul> | But it would also mean maybe having something that actually freaking works, too. |
20:19 | < Consul> | Yes |
20:19 | < Consul> | Not in the Inner loop, though. |
20:19 | <@ToxicFrog> | That is entirely doable but would indeed require more complex bindings |
20:20 | < Consul> | Where the actual DSP happens. |
20:20 | < Consul> | Well, this is stuff we want to do anyway. |
20:20 | <@ToxicFrog> | The simplest interface I can think of is one where you can define a param as a function, not a value, and when that param is needed it calls the function to calculate the effective value |
20:20 | <@ToxicFrog> | That's fairly easy to do and might do most of what you need from runtime scripting |
20:20 | < Consul> | We want to create a class for OSC as well. |
20:21 | < Consul> | (OSC == Open Sound Control, a control signal system like but more advanced than MIDI) |
20:22 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
20:22 | < Consul> | ToxicFrog: And then functions can be written in addition that could alter those return values in real time... |
20:22 | < Consul> | Well, control time. |
20:22 | < Consul> | Not audio time. |
20:23 | < Consul> | All in Lua. |
20:23 | <@ToxicFrog> | Yeah |
20:23 | < Consul> | So interesting things can be scripted as part of the preset. |
20:23 | <@ToxicFrog> | Although, what do you mean by "alter those return values at control time"? |
20:23 | < Consul> | I'm thinking in terms of the way control signals flow in a synthesis engine. |
20:24 | < Consul> | You have a DSP function, like a filter, that takes an audio input, outputs audio, but has several other inputs for parameters that are controls. |
20:24 | <@ToxicFrog> | Right |
20:24 | < Consul> | The values for those control parameters would come from the Lua script. |
20:25 | < Consul> | Meaning that Lua scripts could be written to do other, fancier things to those control signals before handing it over to the DSP object. |
20:25 | <@ToxicFrog> | Yes |
20:25 | < Consul> | Such scripts can also be saved as part of the preset. |
20:25 | <@ToxicFrog> | Yes... |
20:26 | < Consul> | As long as Lua can pull data from the OSC object(s), that allows the sound designer a lot of power. |
20:29 | <@ToxicFrog> | Aah |
20:29 | <@ToxicFrog> | That's the bit I was missing that distinguishes this from parameters-as-functions |
20:29 | <@ToxicFrog> | And that's just a matter of simple bindings |
20:29 | < Consul> | Think in terms of routing signals |
20:29 | | Reiver [~reaverta@Admin.Nightstar.Net] has joined #Code |
20:29 | < Consul> | Like on an analog modular synth. |
20:29 | | mode/#code [+o Reiver] by ChanServ |
20:30 | < Consul> | Wait a minute... |
20:30 | <@ToxicFrog> | Assume that I know nothing about signal processing. |
20:30 | <@ToxicFrog> | Because I don't. |
20:30 | < Consul> | You mean to tell me that all of the misunderstanding I've had in this channel results from my using the term parameter in a different way? |
20:31 | < Consul> | Wow, I have been stupid after all. |
20:31 | < Consul> | Not parameters as in arguments for functions... |
20:32 | < Consul> | But "parameters" as in a knob setting on a synthesizer. |
20:32 | <@ToxicFrog> | I am understanding "parameter" here as a value that controls the behaviour of some device. |
20:32 | <@ToxicFrog> | Yes. |
20:32 | < Consul> | Exactly! |
20:32 | <@ToxicFrog> | I note that fundamentally there is no different here between arguments to a function and (say) global variables. |
20:33 | < Consul> | Here's how to think about signal routing: |
20:33 | <@ToxicFrog> | If the "function" is the synth, its inputs are the knobs and...the incoming signal, or a key pressed by the user, or the like? but it doesn't matter whether those are arguments or not. |
20:33 | < Consul> | An oscillator emits a signal, which is a raw waveform, to be processed... |
20:33 | <@ToxicFrog> | So, there's no misunderstanding here as to the nature of parameters. |
20:33 | < Consul> | That signal can now be sent into any number of "modules", to process it. |
20:33 | < Consul> | Like a filter. |
20:34 | <@ToxicFrog> | Right. |
20:34 | < Consul> | So, a signal route might go: |
20:34 | <@ToxicFrog> | To me, this actually makes the parameters more like function arguments, not less |
20:34 | <@ToxicFrog> | It can be envisioned bashwise: |
20:34 | < Consul> | oscillator -> filter -> output amp (in the software sense) -> sound card |
20:34 | <@ToxicFrog> | oscillator | filter1 param-list | filter2 param-list | filter3 param-list | ... | filterN param-list > /dev/sdp |
20:34 | <@ToxicFrog> | /dev/dsp, even |
20:35 | < Consul> | Routing of signals can be serial or parallel. In fact, a lot of times, they're parallel. |
20:35 | < Consul> | A lot like that, yes. |
20:35 | < Consul> | On an analog modular synth... |
20:35 | <@ToxicFrog> | So we do in fact agree on what parameters are. |
20:35 | < Consul> | Those routes are patch cords. |
20:35 | <@ToxicFrog> | Yes. |
20:35 | <@ToxicFrog> | that much I am aware of. |
20:35 | < Consul> | The paradigm inside a computer is pretty much the same. |
20:36 | <@ToxicFrog> | The modules are interconnected with physical cables, and they are configured by knobs, sliders, and the like |
20:36 | < Consul> | Yup |
20:36 | <@ToxicFrog> | Anyways. |
20:36 | < Consul> | Now imagine being able to script the behavior of any knob based upon some other factor... |
20:36 | <@ToxicFrog> | what I meant by modules-as-functions is something like this: |
20:36 | <@ToxicFrog> | Er, |
20:36 | <@ToxicFrog> | parameters as functions |
20:36 | <@ToxicFrog> | param1 = 5.0; |
20:37 | <@ToxicFrog> | param2 = 16.0; |
20:37 | <@ToxicFrog> | param3 = function() return (param1+param2)/2 end; -- average of 1 and 2 |
20:37 | < Consul> | Okay... |
20:37 | <@ToxicFrog> | Thus, as 1 and 2 are adjusted, 3 follows according to its own code. |
20:37 | < Consul> | Ah, I see! |
20:38 | <@ToxicFrog> | That is to say, whenever param3 is asked for by the program, the function is called and its return value is used |
20:38 | <@ToxicFrog> | Whereas 1 and 2 are simply returned as is |
20:38 | <@ToxicFrog> | What you seemed to be talking about WRT OSC objects and whatnot is the ability for these functions to draw information from other modules' parameters, and so forth |
20:39 | <@ToxicFrog> | Which is conceptually the same thing, but requires more work |
20:39 | < Consul> | Let me point you to something I wrote, that's actually kind-of embarrasing, but it's all I have for now: |
20:39 | < Consul> | Ah, I need voice... |
20:40 | | mode/#code [+oovvv AFKSkull Vornicus Shoukanjuu Consul crem] by ToxicFrog |
20:40 | <+Consul> | http://code.google.com/p/nuclear-project/wiki/KeyFrameParameterization |
20:40 | <+Consul> | That's an idea I have for a UI idea for a sampler. |
20:41 | <+Consul> | idea-- |
20:41 | <+Consul> | It's rough, and has bits that are hard to understand. I did my best, but I intend to draw some diagrams to help out. |
20:41 | <@ToxicFrog> | Hmm. This key frame idea seems like a less general form of functional parametrization :) |
20:41 | <+Consul> | Anyway, I need to head out to the store. I'll be back a little later. |
20:42 | <+Consul> | Implemented the way I see it in my head, it eliminates LFOs and envelopes. |
20:42 | <+Consul> | And makes for a much more programmable synth/sampler. |
20:42 | <@ToxicFrog> | I have no idea what either of those are. |
20:43 | <+Consul> | Modulation sources: they change the value of a target parameter. |
20:43 | <@ToxicFrog> | Ok |
20:44 | <@ToxicFrog> | Those too I think are just a less general form of param = f(...) |
20:44 | <+Consul> | Well, you have to make it friendly to musicians. |
20:45 | <+Consul> | Have you ever seen Spinal Tap? Those are the people that use things like this. :-/ |
20:45 | <@ToxicFrog> | I haven't. |
20:45 | <@ToxicFrog> | Hmm. |
20:45 | <@ToxicFrog> | Ok, so you have widgets that create functions :P |
20:45 | <+Consul> | Basically. |
20:45 | <@ToxicFrog> | Internally it's stored as a function, or possibly as inputs to such a widget that are converted into a function at load time. |
20:46 | <@ToxicFrog> | The user sees a widget they can use to get the parameters they want, and if they're comfortable with a bit of math they can write their own functions. |
20:46 | <+Consul> | Basically, yes. |
20:47 | | AnnoDomini [AnnoDomini@Nightstar-28960.neoplus.adsl.tpnet.pl] has quit [Ping Timeout] |
20:47 | <@ToxicFrog> | Cool. |
20:47 | | AnnoDomini [AnnoDomini@Nightstar-29598.neoplus.adsl.tpnet.pl] has joined #Code |
20:47 | | mode/#code [+o AnnoDomini] by ChanServ |
20:48 | <+Consul> | Anyway, gotta go now. BBL |
21:26 | | Thaqui [~Thaqui@Nightstar-13764.jetstream.xtra.co.nz] has joined #code |
21:26 | | mode/#code [+o Thaqui] by ChanServ |
21:27 | <+Consul> | You'd think an aloe vera plant wouldn't be too hard to find... |
21:29 | <@ToxicFrog> | You'd think so, yes. |
21:29 | <@ToxicFrog> | But you'd be wrong! |
21:29 | <@ToxicFrog> | Oh so wrong |
21:29 | <+Shoukanjuu> | >_> |
21:30 | <+Consul> | Hehe |
21:30 | <+Shoukanjuu> | So I played Soul Calibur 4 SO MUCH that I broke my 360. |
21:32 | <+Shoukanjuu> | The drive still opens, so it's not the drive, directly. I think it's that the laser got hit by the disc, or something |
21:32 | <+Consul> | Wow. How lucky were they to actually get lua.org? Three-letter domain names are a lost cause anymore. |
21:32 | <+Shoukanjuu> | Haha |
21:42 | <@ToxicFrog> | Well, the language has been around since the 90s |
21:42 | <@ToxicFrog> | I don't know when they registered the domain name, but it was probably quite some time ago |
21:43 | | * ToxicFrog checks |
21:43 | <@ToxicFrog> | The first public release was in 94, and the mailing list was up and running by 97 |
21:44 | <@ToxicFrog> | Aha! lua.org went hot in 2001, although it had a website on another domain before that. |
21:44 | <+Consul> | 2001 is recent enough for any 3-letter domain to be tough to find. :-) |
21:45 | <+Consul> | I was making a dumb joke anyway. |
21:45 | <+Consul> | Well, if Lua's fast enough to allow 3D game designers to script complete levels without it affecting real-time performance, it'll probably be good enough for me. |
21:46 | <+Consul> | The thing is, we don't have a slower control rate in our system we're designing. Control signals are processed at the audio rate. In fact, that's key to some of the features I want to try implementing. |
21:47 | <+Consul> | There's also an event-rate which happens upon, well, an event happening. |
21:47 | <+Consul> | I suppose it's up to the programmer of the synth in question. |
21:47 | <@ToxicFrog> | Nod |
21:48 | <+Consul> | For my ubersampler idea, I want control signals and audio signals to be essentially the same. |
21:48 | <@ToxicFrog> | As long as you're just using it as a configuration language it doesn't really matter how fast it is, since all the code gets executed at load or save time |
21:48 | <+Consul> | An integrated scripting engine will need to be running all the time. |
21:48 | <@ToxicFrog> | For functional parameters, I suspect it will come down to making sure people don't write expensive parameters, or possibly abusing memoization or precacheing of the graphs |
21:48 | <+Consul> | So it can make different things happen upon different events. |
21:49 | <@ToxicFrog> | That's not "all the time", that's "when events occur" |
21:49 | <+Consul> | Well, yeah. |
21:49 | <+Consul> | So, we're still okay, I'm sure. |
21:49 | <@ToxicFrog> | Should be |
21:49 | <+Consul> | But if someone wants to insert a script right on a signal... |
21:49 | <+Consul> | It's up to them to make sure it doesn't kill their CPU, I guess. |
21:50 | <+Consul> | Scripting events and parameters is what allows for things like articulations and the like. |
21:51 | <@ToxicFrog> | Nod |
21:51 | <+Consul> | Where one can control many parameters based upon the combination of a few. |
21:51 | | You're now known as TheWatcher[T-2] |
21:51 | <@ToxicFrog> | Anyways, Lua is designed to be both small and fast, and it excels at it; it's much slower than C, but one of the fastest interpreted languages around. |
21:51 | <+Consul> | Kontakt 3, the big sampler from Native Instruments, has just such a scripting engine. |
21:52 | <+Consul> | But Kontakt's scripting doesn't operate in signals, just parameters. |
21:52 | <+Consul> | And the interface, so you can make quasi-custom GUIs with it. |
21:52 | <@ToxicFrog> | And if it turns out not to be fast enough, it probably wouldn't be hard to get it to emit an IR that can be executed in C++ more quickly. |
21:53 | <+Consul> | Ooh, that's an idea... |
21:54 | <+Consul> | There are a crapload of Lua-related things in the Ubuntu repositories. |
21:54 | <+Consul> | I tried finding those that apply to me. |
21:54 | <@ToxicFrog> | Indeed there are. |
21:54 | <+Consul> | C++ binding, and filesystem library in particular. |
21:55 | <+Consul> | But I have liblua5.1 and lua5.1, and related files. |
21:55 | <@ToxicFrog> | For now, start with lua5.1, liblua5.1-0, and liblua5.1-0-dev |
21:55 | <+Consul> | Oh, and the related devs |
21:55 | <@ToxicFrog> | Lua comes with basic filesystem libraries and similar |
21:55 | <+Consul> | Yeah, I have those. |
21:55 | <+Consul> | Well, I already got those other things, so... |
21:55 | <@ToxicFrog> | libluafilesystem is for stuff like stat() and link() support |
21:56 | <@ToxicFrog> | So just start with basic lua for now, if you need more libraries you know where to find them |
21:56 | <+Consul> | This is all definitely staying on the UI side. The engine can stay separate from the Lua stuff. |
21:56 | | You're now known as TheWatcher[zZzZ |
21:56 | | You're now known as TheWatcher[zZzZ] |
21:56 | <+Consul> | Sorry, I'm trying to decide how to organize things. |
21:56 | <@ToxicFrog> | Parameter saving/loading is part of "the UI"? |
21:57 | <+Consul> | Yeah, the engine just does what you tell it to. |
21:57 | <+Consul> | Well, there are three layers, really. |
21:57 | <@ToxicFrog> | As for C++ bindings - it's clean C, and will thus compile as C++ (and the ubuntu version comes with a "lua.hpp" that includes the necessary keywords) |
21:57 | <@ToxicFrog> | So you can use the C API directly. |
21:58 | <+Consul> | There's the "dumb engine" layer, the "smarter wrapper around that engine layer, where Lua would live, and the GUI. |
21:58 | <+Consul> | So, just #include <lua.hpp> and I'm golden? |
21:58 | <@ToxicFrog> | If you want a more C++ish interface - "class lua_State" and so forth - I don't recall if there's one in ubuntu, but there's probably several in the lua-users wiki, or you can roll your own |
21:58 | <@ToxicFrog> | But the C API should be fine, especially to start with |
21:59 | <@ToxicFrog> | But yeah, do that in your C++ code and that gives you access to all the Lua functions |
22:02 | <@ToxicFrog> | I take it that your design looks something like: the UI mediates between the user and the "smart engine"; the smart engine manages configuration data, functional parameters, and the like, and is responsible for setting up the modules of the dumb engine based on those params; and the dumb engine consists of the inner modules that do primitive operations and can be interconnected and configured by the higher layer |
22:02 | <@ToxicFrog> | s? |
22:02 | <+Consul> | That's pretty much it, yes. |
22:03 | <+Consul> | But nothing is set in stone. |
22:03 | <+Consul> | Like I said, right now, we're just writing some useful classes. |
22:03 | <+Consul> | Bottom-up like. |
22:04 | <+Consul> | But there's really no reason why the smart and dumb parts of the engine couldn't be one executable, so to speak. |
22:04 | <+Consul> | But separating the two would allow some flexibility with new interfaces. |
22:05 | <+Consul> | Someone could write a new "smart wrapper" for the same core engine and implement some neat ideas of their own. |
22:08 | <@ToxicFrog> | fundamentally, I don't think it matters that much if they're seperate executables or one executable with nicely seperable libraries. |
22:09 | <@ToxicFrog> | Except that the latter won't have IPC overhead and will thus be faster on nearly all systems. |
22:09 | <+Consul> | I guess I'll have to do it that way, then. |
22:09 | <@ToxicFrog> | And is probably a generally better idea. |
22:09 | <+Consul> | Hopefully, I can learn how. |
22:09 | <@ToxicFrog> | Good IPC Is Work. |
22:09 | <@ToxicFrog> | Libraries are much easier. |
22:10 | <+Consul> | All I get is how C++ is the worst choice ever for making linked libraries. |
22:10 | <+Consul> | But it's what I know. |
22:10 | <+Consul> | And even then, not well. |
22:11 | <@ToxicFrog> | (initial cut at this sort of thing: the dumb engine is a library, or set of libraries, of DSP cores using clearly-defined interfaces. The smart engine is a program which links against this library, configuring and invoking the DSP cores as needed.) |
22:11 | <@ToxicFrog> | You could always do it in plain C, although if you're used to stuff like destructors and exceptions you may find it kind of cramped. |
22:11 | <@ToxicFrog> | Or do it in C++ but make your interfaces in plain C. |
22:11 | <+Consul> | Part of the issue is, the other developer is also a C++ guy. |
22:12 | <@ToxicFrog> | Or just write the whole thing in C++, compile it all with the same compiler and the same settings, and let the linker handle it rather than doing dlopen() tricks and you should be fine. |
22:12 | <+Consul> | He's the one who's actually made progress and made things that work, like an abstract class for JACK for making easy JACK clients. |
22:13 | <@ToxicFrog> | You're basically fine if you're making a modular program and then building and linking all the modules yourself. |
22:13 | <+Consul> | When you say "interfaces in plain C" you mean the header file? |
22:13 | <@ToxicFrog> | And you should be fine if you're making a library, compiling it, and then linking against it later. |
22:13 | <+Consul> | I think that was basically the plan. |
22:13 | <@ToxicFrog> | Where the spiders come out is when you want to explicitly load DSOs at runtime. |
22:14 | <+Consul> | We're not trying to make dynamic libs that are standalone, like libsamplerate and stuff like that. |
22:14 | <@ToxicFrog> | Right |
22:14 | <@ToxicFrog> | In that case go with one nicely modularized program and you're golden |
22:15 | <@ToxicFrog> | With careful design it should be easy for people who want to, say, make alternate frontends to get the source, peel away the one you provide and replace it with their own |
22:15 | <+Consul> | We're coding as header-only libraries, like the Boost libs. |
22:15 | <+Consul> | So you just include in-line. |
22:17 | <+Consul> | We have our own namespace defined in each one. |
22:17 | <+Consul> | Well, not "each class has its own namespace." |
22:17 | <+Consul> | but... |
22:17 | <+Consul> | Oh, never mind. |
22:18 | <@ToxicFrog> | Hang on |
22:18 | <@ToxicFrog> | So this means each header contains a complete class definition including method definitions? |
22:18 | <@ToxicFrog> | AUGH NO BAD BAD BAD |
22:18 | <+Consul> | Yes. |
22:19 | <+Shoukanjuu> | 0 == "0" |
22:19 | <+Consul> | Well, too late now. |
22:20 | <+Consul> | I know, it seemed to me to eliminate the idea of an unchanging .h file while the .cpp can change if it needs to. |
22:20 | <@ToxicFrog> | Consul: ok, so what happens when file a.cpp and b.cpp both need to use class C, #include it, and then the linker totally loses its shit because now you have two classes with the same name? |
22:20 | <+Consul> | We have ifndef statements in each one. |
22:20 | <@ToxicFrog> | No, no |
22:20 | <@ToxicFrog> | The first file #includes <class.hpp> |
22:20 | <@ToxicFrog> | The second file also #includes <class.hpp> |
22:21 | <@ToxicFrog> | In neither of these is it already defined, so each one gets its own class definition |
22:21 | <@ToxicFrog> | This is not "it gets included multiple times", it's "two different files each include it seperately" |
22:21 | <@ToxicFrog> | these files are then compiled. |
22:21 | <@ToxicFrog> | then the linker tries to combine them into an exe. |
22:21 | <@ToxicFrog> | Whoops, we have two definitions for Class. |
22:22 | <+Consul> | Well, why do the Boost libs, which are written by people incredibly well-versed in C++, do it this way, then? |
22:22 | <@ToxicFrog> | Boost, IIRC, is entirely a template library |
22:23 | <+Consul> | I'll have to bring this up with the other dev, then. |
22:24 | <@ToxicFrog> | I admit that I'm mostly coming at this from a C perspective, it's possible there's tricks you can do with C++ that make this possible |
22:24 | <@ToxicFrog> | Even if there is, however, I would argue it's a terrible idea; each class now has to be compiled in every single file that uses it anywhere, and changing any class, even if the interface is unchanged, also requires a recompile of every other file that uses that class |
22:25 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
22:25 | <@ToxicFrog> | And unlike Boost, this is a library you're using internally, not something you're releasing as a standalone library that needs to worry about ABI incompatibilities. |
22:25 | <+Consul> | I'm going to post an email with a copy of this conversation to our mailing list... |
22:26 | <+Consul> | Actually, scratch that. I'll send him a private email instead. |
22:26 | <@ToxicFrog> | I *suspect* Boost can get away with this because it's entirely templated, which means it has no actual class definitions |
22:26 | <@ToxicFrog> | What it has are macros that expand into type-specific class definitions at preprocessor time |
22:28 | <@ToxicFrog> | Actually, I might as well test this mysrelf |
22:29 | <+Consul> | Okay, I emailed him on the issue. |
22:29 | <+Consul> | But he knows more about C++ than I do. |
22:31 | | Reiver [~reaverta@Admin.Nightstar.Net] has joined #Code |
22:31 | | mode/#code [+o Reiver] by ChanServ |
22:31 | <+Consul> | It wouldn't be hard to reverse things, I think. |
22:31 | <@ToxicFrog> | Hmm |
22:31 | <+Consul> | And to be honest, I wouldn't mind. |
22:31 | <@ToxicFrog> | Ok, on further testing, I am in fact wrong |
22:31 | <+Consul> | I was originally writing separate headers and cpp files. |
22:32 | <+Consul> | Oh? |
22:32 | <@ToxicFrog> | I think, one moment |
22:33 | <@ToxicFrog> | Yeah, I'm wrong |
22:33 | <@ToxicFrog> | You can fully define a class in a header file and the compiler will do the right thing |
22:33 | <@ToxicFrog> | That doesn't, however, make it the right thing to do! |
22:33 | <@ToxicFrog> | If nothing else it massively slows down your build system. |
22:33 | <+Consul> | Well, that was a pointless email, now. |
22:33 | <@ToxicFrog> | And makes it difficult to seperate the interface and the implementation. |
22:34 | <+Consul> | We've already been fighting enough over the implementation of this thing... |
22:38 | | Reiver [~reaverta@Admin.Nightstar.Net] has quit [Ping Timeout] |
22:40 | <+Consul> | Anyway, this Lua thing interests me, and I'll see what I can do to make it easy to use. |
22:42 | | AnnoDomini [AnnoDomini@Nightstar-29598.neoplus.adsl.tpnet.pl] has quit [Quit: "Even in death, a wizard cannot be trusted."] |
22:45 | | Reiver [~reaverta@Admin.Nightstar.Net] has joined #Code |
22:45 | | mode/#code [+o Reiver] by ChanServ |
23:30 | | Vornicus [~vorn@Admin.Nightstar.Net] has quit [Ping Timeout] |
--- Log closed Fri Aug 08 00:00:20 2008 |