loopdub-devel Mailing List for LoopDub
Brought to you by:
radarsat1
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(4) |
Sep
(6) |
Oct
|
Nov
|
Dec
(2) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(21) |
2008 |
Jan
(9) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2010 |
Jan
|
Feb
|
Mar
(6) |
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Stephen S. <rad...@gm...> - 2010-07-03 15:07:49
|
Hello, I just decided to take all current changes and uploaded release 0.4 of LoopDub, also with a Ubuntu deb binary package to ease installation. Steve |
From: Stephen S. <rad...@gm...> - 2010-03-15 01:45:10
|
Thanks, maybe it is a simple bug in the file reading code. Haven't had a chance to try AV yet, it might be a while before I have some free time to do so. Steve On Mon, Mar 15, 2010 at 1:33 AM, Hugh Lovette <hug...@gm...> wrote: > If it isn't too late, why don't you hold on and let me test a bit > here. I tried on another machine and it seems to run better, running > under jack as well, though not when jack is set to 48000, in which > case it gives the following: > > ./loopdub LoopSet/ > MIDI configuration read successfully. > LoopDub started... > MIDI initialized. > No programs found. > RtError in Player::Initialize(): RtApiJack::probeDeviceOpen: the > requested sample rate (44100) is different than the JACK server rate > (48000). > Couldn't initialize audio player. > > Note that this is the reverse of what I saw on my normal machine: I > could run with jack at 48000 (though samples played at double [or > something] speed), but if I tried at 44100 I got the error above, > though with sample rates reversed, as would make sense (well, not > really, or we wouldn't be discussing all this) > > I got a segfault with I tried w/ .loopdub.conf - odd, huh? So, runs > fine w/ no loopdub.conf without jack or with jack set at 44100, plays > samples of both rates fine, though probably wrong speed if wrong > sample rate - don't imagine it magically fixing that. Does not start > w/ jack at 48000 -errors as above. Segfaults when I have > .loopdub.conf. > > Maybe I have a screwed up .conf file. > > Gotta run, though, just wanted to tell you I'd seen this conflicting > behavior and should probably explore a bit more here to make sure I'm > not sending you on a wild goose chase by telling you something wrong > or by missing the obvious > This is all with loopdub 0.3, will try compiling fresh from git later. > > Thanks > > On Sun, Mar 14, 2010 at 2:48 PM, Stephen Sinclair <rad...@gm...> wrote: >> Huh, I've never even heard of AV Linux. Looks like there's a Live CD >> so I'll download it and see if I can debug with that. Weird that it >> segfaulted.. >> >> ah, I should have predicted the "not a git repository" error messages >> however. The util/version.sh script uses git to determine the current >> version. I would normally replace this in a tarball release. >> >> cheers, I'll get back to you to say if I can test it with AV. >> >> Steve >> >> On Sun, Mar 14, 2010 at 6:35 PM, Hugh Lovette <hug...@gm...> wrote: >>> While it seemed to compile when I just changed "AC_DEFUN" to >>> "m4_define" in configure.ac it segfaulted immediately. I'll attache >>> the output from compiling in case it is helpful. >>> ./loopdub ~/LoopSet/ >>> MIDI configuration read successfully. >>> LoopDub started... >>> Segmentation fault >>> >>> ...I see now there are a bunch of "fatal: Not a git repository..." >>> errors from autogen.sh (see attached). >>> >>> ...I tried the second suggestion and did not see any errors while >>> compiling, but still got the segfault :( >>> >>> autoconf -V = 2.65 >>> >>> I'm running AV Linux - 32 bit only (I bet that is one major difference >>> from yours right there) but based on debian testing... ran out of the >>> box, and ran better with relatively minimal tweaking, unlike others I >>> tried. I'm using the on-board soundcard for now. >>> >>> Thanks a lot for your help with this! >>> >> > |
From: Stephen S. <rad...@gm...> - 2010-03-14 21:48:59
|
Huh, I've never even heard of AV Linux. Looks like there's a Live CD so I'll download it and see if I can debug with that. Weird that it segfaulted.. ah, I should have predicted the "not a git repository" error messages however. The util/version.sh script uses git to determine the current version. I would normally replace this in a tarball release. cheers, I'll get back to you to say if I can test it with AV. Steve On Sun, Mar 14, 2010 at 6:35 PM, Hugh Lovette <hug...@gm...> wrote: > While it seemed to compile when I just changed "AC_DEFUN" to > "m4_define" in configure.ac it segfaulted immediately. I'll attache > the output from compiling in case it is helpful. > ./loopdub ~/LoopSet/ > MIDI configuration read successfully. > LoopDub started... > Segmentation fault > > ...I see now there are a bunch of "fatal: Not a git repository..." > errors from autogen.sh (see attached). > > ...I tried the second suggestion and did not see any errors while > compiling, but still got the segfault :( > > autoconf -V = 2.65 > > I'm running AV Linux - 32 bit only (I bet that is one major difference > from yours right there) but based on debian testing... ran out of the > box, and ran better with relatively minimal tweaking, unlike others I > tried. I'm using the on-board soundcard for now. > > Thanks a lot for your help with this! > |
From: Stephen S. <rad...@gm...> - 2010-03-14 14:11:05
|
Hi, thanks for the test samples. Here are my results. with git version: - ALSA, all loops play correctly. - Jack 44100, all loops play correctly. - Jack 48000, all loops play correctly. (This involved editing .loopdub.conf between Jack sessions of course.) I noticed some definite looping problems that happen sometimes (but not every time?) if you first load a 48 kHz loop then a 44.1 kHz loop and vice-versa, so that maybe needs looking at. But in general it works as expected. I didn't notice any double-speed problems. with version 0.3: - ALSA, all samples play correctly but it obviously plays 48 kHz loops at a different pitch than 44.1 kHz loops. - Jack 44100, doesn't work. It is hardwired to request 48 kHz. - Jack 48000, all loops play correctly for me. I didn't get this double-speed problem you describe. So.. there must be some difference between our systems. I think it'd be best to try the latest version, so that at least we're talking about the same thing, but I still find it confusing as I can't reproduce it even on version 0.3. It may even come down to having different sound hardware, which demands different Jack settings, etc. Your autoconf problem is unexpected, I looked it up and it seems related to my use of AC_DEFUN before AC_INIT. Can you tell me which version of autoconf you are using? (autoconf -V) Also which OS are you using? Two things you could do: In configure.ac, try changing the word "AC_DEFUN" to "m4_define" and tell me if it still breaks. If it is still a problem, you should be able to at least side-step the problem by just removing this line and replacing the word "LOOPDUB_VER" with "0.4-git" or something similar everywhere in the file. (and rerunning autogen.sh.) Let me know how it goes. Thanks again for all your testing, it's very helpful! Steve On Sun, Mar 14, 2010 at 6:50 AM, Hugh Lovette <hug...@gm...> wrote: > No problem about cross posting, we can move the whole discussion there > if you like, but I'll use email this one last time and wait until > you've copied these over. > > You are right, I'm running the 3.0 compiled from source. When I > grabbed the latest from git I remembered that I had to edit > bootstrap.sh to point to local, more recent versions of rtmidi and > rtaudio since the included links were out of date. > > I'm attaching files as requested. They're random drum loops from some > torrent or the other. I stayed lazy in created additional test samples > just using a demo pattern in hydrogen recorded with jack_capture, then > made a resampled copy in audacity. They also play way too fast when > jack is running. Oh, and the original tests (C01.4*.wav) were mono, > the new (test4*.wav) stereo. > > I just tried the latest fro git and ran onto the following, not sure > what to try: > ../LoopDub$ ./autogen.sh > libtoolize: putting auxiliary files in `.'. > libtoolize: linking file `./ltmain.sh' > libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `m4'. > libtoolize: linking file `m4/libtool.m4' > libtoolize: linking file `m4/ltoptions.m4' > libtoolize: linking file `m4/ltsugar.m4' > libtoolize: linking file `m4/ltversion.m4' > libtoolize: linking file `m4/lt~obsolete.m4' > libtoolize: Consider adding `-I m4' to ACLOCAL_AMFLAGS in Makefile.am. > configure.ac:4: error: m4_divert_push: cannot change diversion to > `GROW' inside m4_expand > configure.ac:4: the top level > autom4te: /usr/bin/m4 failed with exit status: 1 > aclocal: autom4te failed with exit status: 1 > Error running aclocal. > > > Thanks - let me know what I can do to test > |
From: Stephen S. <rad...@gm...> - 2010-03-12 15:51:14
|
Hi Simon, Last night I sat down and wrote a proper autotools configuration for LoopDub. I'd been meaning to do it for a while anyways. I also decided to just include the RtAudio and RtMidi sources directly into the repository, so now no bootstrap is required on Linux. Steve On Sat, Mar 6, 2010 at 9:02 PM, Stephen Sinclair <rad...@gm...> wrote: > Hi, > > On Fri, Mar 5, 2010 at 7:35 PM, Simon Lewis <sim...@sl...> wrote: >> Hello LoopDub >> >> I am trying to build an rpm for Fedora 12 (64 Bit). > > Cool! > > >> With the exception of rtmidi all other libdeps are already installed on this >> Pc. >> >> I do not want to run ./bootstrap.sh as this downloads older version of the >> libraries which are then statically linked. > > You could feel free to include the RtMidi sources directly as a diff > on the tarball if you want. Maybe RtMidi could use an RPM package > though. > > As for the fact that is uses older versions, I guess LoopDub needs to > be updated to use the newer versions but I can't promise when that > will happen. In the meantime you have to decide whether to try it > against the newer versions or simply statically link the old versions > ignoring the RPM packages. > > Feel free to request more strongly that I improve things. I won't > spend too much time on LoopDub as I have other things to worry about > these days, but I'll happily put a little work into it to make > packaging easier. I'm not currently running Fedora however, so please > tell me specifics. > >> How do I export the libpaths to SConstruct? > > Not sure. I've switched most of my other projects to autotools but > didn't get around to switching LoopDub yet. > > > Steve > |
From: Stephen S. <rad...@gm...> - 2010-03-06 21:03:02
|
Hi, On Fri, Mar 5, 2010 at 7:35 PM, Simon Lewis <sim...@sl...> wrote: > Hello LoopDub > > I am trying to build an rpm for Fedora 12 (64 Bit). Cool! > With the exception of rtmidi all other libdeps are already installed on this > Pc. > > I do not want to run ./bootstrap.sh as this downloads older version of the > libraries which are then statically linked. You could feel free to include the RtMidi sources directly as a diff on the tarball if you want. Maybe RtMidi could use an RPM package though. As for the fact that is uses older versions, I guess LoopDub needs to be updated to use the newer versions but I can't promise when that will happen. In the meantime you have to decide whether to try it against the newer versions or simply statically link the old versions ignoring the RPM packages. Feel free to request more strongly that I improve things. I won't spend too much time on LoopDub as I have other things to worry about these days, but I'll happily put a little work into it to make packaging easier. I'm not currently running Fedora however, so please tell me specifics. > How do I export the libpaths to SConstruct? Not sure. I've switched most of my other projects to autotools but didn't get around to switching LoopDub yet. Steve |
From: Simon L. <sim...@sl...> - 2010-03-05 20:17:51
|
Hello LoopDub I am trying to build an rpm for Fedora 12 (64 Bit). With the exception of rtmidi all other libdeps are already installed on this Pc. I do not want to run ./bootstrap.sh as this downloads older version of the libraries which are then statically linked. How do I export the libpaths to SConstruct? Regards, Simon |
From: Stephen S. <rad...@gm...> - 2009-07-04 16:35:53
|
Hi, There hasn't been any activity on loopdub in ages for various reasons, but: I just recently moved the repository to github. Previously I was hosting the git repository by dumb http on the sourceforge website, so I thought it might make collaboration easier by using github. Sourceforge has recently added proper git support, and I may clone the "official" repository there one day, but github makes forking and collaboration very easy so it is a good solution until I feel like dealing with SF again. Fortunately the use of git makes moving things around like this really easy. This was spurred by some contributed patches by Nick Seow, who ultimately wants to figure out why the display update code seems to cause audio glitches. His patches so far have been to try and fix some memory handing issues in the code. The patches are not yet merged into master, but are available in a branch called "nick". On my part, I'm suggesting we properly separate the display and audio engines into different process that use OSC to communicate. As usually I don't have much (any) time to work on LoopDub, but I'm happy to merge people's patches and hopefully github will make this easier. Steve |
From: Stephen S. <rad...@gm...> - 2008-01-03 22:23:26
|
> I'd be quite happy to do the coding part of the job, if that's what > you're asking. As far as I'm concerned, the hard part of the job is > close to over, now that we've hammered out most of the design -- > something that I could not have done by myself. It has been a pleasure > thinking with you, by the way. Yeah, it's great that you've shown interest in my little audio project. :) I just mentioned that to warn you in case my replies start to come slower over the next few months. However, I'll try to be ready to commit patches whenever you have something. I really enjoy working on this program, but if you look at the logs you'll see that there were pretty much no commits in the last couple of years, except in december.. I'm working on a PhD at the moment and I have no idea how busy I'll be this year. In any case, I'll post if I come up with something for the MIDI stuff. I'm not sure how to implement what we discussed.. It seems that trying to set the GUI sliders directly from the MidiValue class isn't ideal, because of things like the Button Mode selection. Perhaps what's needed is instead of binding CC messages to GUI sliders, to bind them instead to messages (methods) that the LoopOb understands. I guess this would have to be a bidirectional communication. Of course, Button Mode selection isn't associated with a LoopOb, but is global. That may just be a different case entirely.. Perhaps the LoopDub class should also be able to receive messages from MidiValue. Steve |
From: Stephen S. <rad...@gm...> - 2008-01-03 22:12:39
|
> 1. Merge the internal and hardware sample rates. > 2. Automatically resample all loops to the hardware sample rate when > they are loaded. That... is a good idea. Why didn't I think of it.. ;-) > Now, what about the clicking problem? Let's run with the Ah, sorry I should have explained that I understand the clicking problem. During real-time resampling, if the hardware buffer size times the ratio between the two sample rates does not work out to an integer, then you will get a partial-sample at the end of every buffer. (i.e., the sample value is sort of spread-out over more than one sample bin.) This won't be an issue if the resampling is done when the loop is loaded. Perhaps it only on the last sample, but I don't know if this would be audible. > So, perhaps we could devise a buffer size that is compatible with most > of those sample rates, and simply print a warning for the user when > they load a sample that is not at one of those sample rates. Not a > fully general solution, but perhaps a practical one? It's possible. What I chose works fine for the usual conversion of 44100 to 48000 (and would scale to 96000): 800 * (44100/48000) * (48000/48000) = 735 However, if we do as you say and resample the loops on load, we no longer need to consider the buffer size, but the total sample size which, when rescaled, should come out to an integer to as to avoid a possible click at the end of the loop. Unfortunately we have no control over the loop length. I can imagine in some cases though, it might be better to shave off a few samples from the original loop before resampling in order to improve the quality of the resampled loop. (so that it comes out to an integer) Steve |
From: Nick T. <nh...@gm...> - 2008-01-03 04:30:42
|
On Jan 2, 2008 10:49 PM, Stephen Sinclair <rad...@gm...> wrote: > (If I didn't add the variables to the configuration file, the values > were initialized to zero, which didn't work too well. :) > :-) > Ideally the InternalSampleRate wouldn't be specified by the user, but > loopdub would just use the sample rate information in the wav file > header. > This would mean a different call to the resampling algorithm for each > loop, however, increasing CPU usage. Not sure it's a good trade-off > if all my loops are encoded at the same samplerate. Perhaps something > more 'intelligent' (i.e., nasty and complicated) could be used to do > the resampling before or after mixing depending on whether all the > loop samplerates are the same. > Here's a proposal for you: 1. Merge the internal and hardware sample rates. 2. Automatically resample all loops to the hardware sample rate when they are loaded. The resampling happens once per loop, at load time, meaning probably-insignificant CPU usage for resampling; the delay caused by the resampling would probably be dwarfed by the time spent reading the file itself. This also means that no resampling is necessary during mixing, since everything is already at the correct sample rate. Now, what about the clicking problem? Let's run with the integer-multiple buffer size solution, and see where it takes us. WAV files could theoretically be at any sample rate, but in practice will almost always be one of the sample rates listed here: http://en.wikipedia.org/wiki/Sample_rate#Audio So, perhaps we could devise a buffer size that is compatible with most of those sample rates, and simply print a warning for the user when they load a sample that is not at one of those sample rates. Not a fully general solution, but perhaps a practical one? |
From: Nick T. <nh...@gm...> - 2008-01-03 04:14:36
|
On Jan 2, 2008 10:58 PM, Stephen Sinclair <rad...@gm...> wrote: > Cool. With this in mind, have you tried any code related to your > suggestion (i.e., storing values in the loopob)? > I'm curious to see if it will work better than what I was trying to do.. > I have not. I will give it some thought, and see what comes out. > I'm expecting the semester to start up again in full force next week, > so if you're interesting in working on this I'm all ears, as I'll have > less time for loopdub in the next few months. > I'd be quite happy to do the coding part of the job, if that's what you're asking. As far as I'm concerned, the hard part of the job is close to over, now that we've hammered out most of the design -- something that I could not have done by myself. It has been a pleasure thinking with you, by the way. |
From: Stephen S. <rad...@gm...> - 2008-01-03 03:58:16
|
> With the point on magnetically controlled knobs aside, I think that we > have arrived at a design that we can both agree on: pick-up > implemented using your algorithm, with the ability to selectively > disable pick-up for different controls. Cool. With this in mind, have you tried any code related to your suggestion (i.e., storing values in the loopob)? I'm curious to see if it will work better than what I was trying to do.. I'm expecting the semester to start up again in full force next week, so if you're interesting in working on this I'm all ears, as I'll have less time for loopdub in the next few months. Steve |
From: Stephen S. <rad...@gm...> - 2008-01-03 03:49:59
|
> The attached patch adds two new configuration parameters to > .loopdub.conf: HardwareSampleRate and InternalSampleRate. > HardwareSampleRate is the sample rate used for the audio output; it > corresponds to Player::m_nHwSampleRate. InternalSampleRate is the > sample rate used for internal processing; it corresponds to the new > static variable Player::m_nSampleRate, which replaces the old > SAMPLE_RATE constant defined in player.h. Very nice, thanks. I've been wanting to do something like that. I'd been thinking of using the command line but the configuration file is a much better solution. Maybe the command line could be used to override the configuration file. I'll look into command line stuff sometime, but for now the configuration file is a real bonus. I committed your patch, plus a small one on top that initializes the m_cfg* variables properly. (If I didn't add the variables to the configuration file, the values were initialized to zero, which didn't work too well. :) > It is arguable that InternalSampleRate and HardwareSampleRate should > be merged; that is, that they should always be the same. The advantage > would be increased simplicity (both in the code and from the user's > perspective); the disadvantage would be decreased flexibility. What do > you think? Actually I just recently added the HardwareSampleRate thing and the dependency on libsamplerate. (after the 0.3 release) This was because in fact on my laptop, ALSA refuses to allow the soundcard to be initialized at 44100 Hz. I guess this is because it doesn't support upsampling in the driver, and the hardware clock probably runs at 48000 Hz. However, I had a huge database of loops that were all encoded at 44100, so they were playing too fast. I had to introduce the upsampling in order to get my loops to play at the right speed. Ideally the InternalSampleRate wouldn't be specified by the user, but loopdub would just use the sample rate information in the wav file header. This would mean a different call to the resampling algorithm for each loop, however, increasing CPU usage. Not sure it's a good trade-off if all my loops are encoded at the same samplerate. Perhaps something more 'intelligent' (i.e., nasty and complicated) could be used to do the resampling before or after mixing depending on whether all the loop samplerates are the same. By the way, here's an open problem: it's somewhat difficult to ensure that there is no clicking due to the differences between buffer sizes before and after resampling. For this reason I chose a very specific buffer size that was an integer multiple of the ratio between 44100/48000. It's a bit specific, and I'd like to make it more general in the future.. the user should be able to specify the buffer size. However, due to resampling, if this ratio doesn't work out to an integer you get a lot of clicking. anyways, thanks for the patch. Steve |
From: Nick T. <nh...@gm...> - 2008-01-02 10:52:54
|
The attached patch adds two new configuration parameters to .loopdub.conf: HardwareSampleRate and InternalSampleRate. HardwareSampleRate is the sample rate used for the audio output; it corresponds to Player::m_nHwSampleRate. InternalSampleRate is the sample rate used for internal processing; it corresponds to the new static variable Player::m_nSampleRate, which replaces the old SAMPLE_RATE constant defined in player.h. The motivation for HardwareSampleRate is to allow the user to choose a sample rate other than 48000Hz, which was previously hard-coded. The motivation for InternalSampleRate is to allow the user to configure LoopDub to choose a sample rate that matches their hardware sample rate; or, alternately, one that matches the sample rate of their loop files, if these two sample rates do not match. It is arguable that InternalSampleRate and HardwareSampleRate should be merged; that is, that they should always be the same. The advantage would be increased simplicity (both in the code and from the user's perspective); the disadvantage would be decreased flexibility. What do you think? |
From: Nick T. <nh...@gm...> - 2008-01-02 09:59:21
|
On Jan 1, 2008 10:10 PM, Stephen Sinclair <rad...@gm...> wrote: > Hi, > > Sorry for the delayed response.. :) > I was preparing to play a set at a new year's party, so I didn't want > to give you a quick answer. You put a lot of thought into your posts > so I like to give myself time to consider carefully before answering. > Not a problem at all. I much prefer a thorough response to a timely one. > (ps. the set went well, though i played so late in the night that > there weren't many people left... loopdub worked perfectly however! > First time doing a set using Linux on a borrowed MacBook Pro.) > Glad to hear it! > > The essential problem here is that it just makes no sense to have MIDI > > pick-up for a controller that can move in a non-stepwise manner; > > Perhaps, but I think it's best to assume that any control can move in > a non-stepwise manner. > That would be the ideal solution, yes. It would be much simpler to not have to make the distinction. And, as you point out, perhaps it would even be necessary. > > My button goes to 64 when I turn it on, and > > 0 when I turn it off, so I can never get to 32. I'm stuck in pick-up > > mode; my button is rendered useless. > > Pick-up mode doesn't need to detect proximity to the current value. > It only needs to remember which side the MIDI control was on (relative > to the GUI value) before going into pick-up mode. > Yes, you're right. I like your algorithm. It seems to encapsulate the essential characteristic of MIDI pick-up, which is that the MIDI control value has to pass through the internal control value before the program will respond to it again. Of course, we're also in agreement that sometimes this just isn't what you want, which is why we want to be able to disable pick-up selectively. > One situation however comes to mind: what about those controllers > where the settable knobs are magnetically controlled? If you send a > MIDI value to one of the knobs, it swings into place over some amount > of time. During this particular delta time, wouldn't you want to > ignore values during the slide? It seems pick-up mode might be useful > for saying "go to this value, but ignore incoming CC messages until > that value is reached." > For such a device, I would say that you would want to enable pick-up mode for its knobs. This would do the right thing when an internal control change causes the hardware control to move; it would also do the right thing when you load a preset or something like that. If you're not in pick-up mode (that is, the hardware control value matches the internal control value), and you load a preset, then the controller sends CCs for each control until the control reaches its new value: thus, the slide in the hardware control value is matched by a corresponding slide in the internal control value. This seems to me to be desirable, not undesirable. Similarly, if any of the controls are in pick-up mode, their CCs will be ignored until they reach the internal value, and then they will slide the rest of the way to their final value. This is, I think, the right thing to do. If a control is in pick-up mode and the movement between its initial value and its final value does not pass through the internal value, then the internal value will not change at all. This is _arguably_ the right thing to do. There may be a better solution, but I think that it is not worth further exploring until we have confirmed that a device with these characteristics actually exists. With the point on magnetically controlled knobs aside, I think that we have arrived at a design that we can both agree on: pick-up implemented using your algorithm, with the ability to selectively disable pick-up for different controls. |
From: Stephen S. <rad...@gm...> - 2008-01-02 03:10:58
|
Hi, Sorry for the delayed response.. :) I was preparing to play a set at a new year's party, so I didn't want to give you a quick answer. You put a lot of thought into your posts so I like to give myself time to consider carefully before answering. (ps. the set went well, though i played so late in the night that there weren't many people left... loopdub worked perfectly however! First time doing a set using Linux on a borrowed MacBook Pro.) I did do a little more work on my midisync branch and I have come to the conclusion that perhaps it was a bad way to start. I still kind of like the idea of the MidiValue class, but the way I was linking the values to specific GUI sliders was probably a bad decision. For instance, it didn't play well when I went to implement the button-mode selection. > Okay, I read your code, and it mostly makes sense to me. One question: > I can't seem to discern the purpose of NEEDSYNC. What is it used for, > precisely? That was just to keep some state information about a given midi value. It wasn't completely thought out yet. > My button goes to 64 when I turn it on, and > 0 when I turn it off, so I can never get to 32. I'm stuck in pick-up > mode; my button is rendered useless. Pick-up mode doesn't need to detect proximity to the current value. It only needs to remember which side the MIDI control was on (relative to the GUI value) before going into pick-up mode. Example, if K is the knob value (which the software remembers from the last CC message) and G is the last GUI value. Let's say Kp and Gp are the previous values. Starting with the button off, and the GUI is moved to position 32. Step 1: K = 0 (button off); G = 32 (slider moved); mode = 'pickup'; Step 2: Kp = 0, Gp = 32; K = 64 (button pressed); If ((Kp <= Gp) == (K >= Gp)) then G = K; else G = Gp; Hm... something like that anyways. > The essential problem here is that it just makes no sense to have MIDI > pick-up for a controller that can move in a non-stepwise manner; Perhaps, but I think it's best to assume that any control can move in a non-stepwise manner. I haven't tested it, but I assume that some MIDI controllers will send non-successive values if you move the knob fast enough. > two concepts are mutually exclusive, since one is designed to avoid > jumps in control values, and the other inherently results in jumps in > control values. Pick-up is only designed to avoid jumps _caused by context switches_ internal to the software. A stream of incoming CC messages with no state change in the software should be processed as if they are always valid. > The complex solution is to allow pick-up to be disabled selectively. I think this isn't a bad idea. > The reason it is necessary to disable MIDI pick-up > entirely for these controllers is the possibility of loading presets > on the controller; this results in jumps in all of the control values, > and would create conflicts if there were pick-up on any controls. I don't really think it would cause problems to load a preset on a controller and have all the values change, they should just be processed as any other incoming CC message. However, I think you're right that it might be useful to be able to disable pick-up for controllers that have controllable knobs. One situation however comes to mind: what about those controllers where the settable knobs are magnetically controlled? If you send a MIDI value to one of the knobs, it swings into place over some amount of time. During this particular delta time, wouldn't you want to ignore values during the slide? It seems pick-up mode might be useful for saying "go to this value, but ignore incoming CC messages until that value is reached." > As I said before, I think that, for now, we should simply not support > non-stepwise movement of controls. We can add support for that later, > but for now let's focus on getting the basic pick-up and sync working. I just don't really think it's even a good idea to differentiate between stepwise and non-stepwise control. Or, put differently, I think it's best to assume that any control can be non-stepwise. For example, in your situation, for configuring a CC to a button. It would be a shame not to support this situation. Steve |
From: Nick T. <nh...@gm...> - 2007-12-30 11:05:57
|
On Dec 29, 2007 10:33 PM, Stephen Sinclair <rad...@gm...> wrote: > Hi, > > I'm afraid I don't have time to give you a point-for-point answer > right now. I've thought about it a bit, but in fact I think a lot > better about these things in C++ rather than in english, so I started > coding a little to see what issues might arise. > Okay, I read your code, and it mostly makes sense to me. One question: I can't seem to discern the purpose of NEEDSYNC. What is it used for, precisely? > I would be interested to know what you think, and how it differs from > your approach. > The main difference (aside from what I address below) is that your approach keeps things more cleanly separated: it keeps the MIDI business with the MIDI code, without getting it mixed into the LoopObs. I understand what you're trying to do there, and I appreciate it. The counterpoint, of course, is that your approach adds a new class, whereas mine does not. It's a trade-off; at this point, I don't feel strongly either way. > There are only two points in your message that I think I disagree > with. First is the necessity of handling this corner case where the > user unplugs a MIDI cable and reattaches it. I have little interest > in handing that case -- if the user is doing such a thing, he'll > expect things to go strange, and a key command 's' to re-synchronize > manually is probably sufficient, as we have now. > That's a reasonable position to take. I think I agree with you, actually. > I think it is quite dangerous to assume that all CC messages will be > exactly 1 tick apart. You mention yourself that it won't handle the > button case -- there may be other cases where the user wants to set > everything to a particular value. (Loading a preset for example.) My > idea for 'pick up' was to only enable that state when a sample is > loaded (i.e., the 'internal' case, a context change.) It might also > be useful for when the user moves a slider, but again, this state is > deterministically available to the program and doesn't depend on the > difference between two successive CC values. > Good point; I hadn't thought of it that way. However, your solution (only enabling pick-up after an internal control change) is still only a partial solution. Suppose that I have a non-auto-syncing controller with buttons on it being used for CCs, specifically for feedback. The feedback on a loop is set to 0, and the button is off, thus effectively also being "zero." Now I move the feedback slider in the GUI, setting it to 32. This is an internal control change, and it puts my button in pick-up mode. My button goes to 64 when I turn it on, and 0 when I turn it off, so I can never get to 32. I'm stuck in pick-up mode; my button is rendered useless. This same situation will happen in any case where we have a control move in a non-stepwise manner when the control is in pick-up mode. The essential problem here is that it just makes no sense to have MIDI pick-up for a controller that can move in a non-stepwise manner; the two concepts are mutually exclusive, since one is designed to avoid jumps in control values, and the other inherently results in jumps in control values. Two solutions to this problem occur to me. One is simple, one is complex. The simple one is to just outlaw non-stepwise movement of controllers. This might be good for a first step. The complex solution is to allow pick-up to be disabled selectively. That is, it can either be disabled for individual controls, or for all controls at once. The first case is for non-auto-positioning controllers that have MIDI CC buttons on them. We disable MIDI pick-up for the buttons, and leave it enabled for the sliders and knobs. The second case is for auto-positioning controllers, which have no use for MIDI pick-up. The reason it is necessary to disable MIDI pick-up entirely for these controllers is the possibility of loading presets on the controller; this results in jumps in all of the control values, and would create conflicts if there were pick-up on any controls. What about loading presets on non-auto-positioning controllers? Trick question; it's not possible, because the controls have to be manually positioned. In more general terms, the sliders and knobs on non-auto-positioning controllers must move in a stepwise manner; they inherently cannot have jumps in their values. Therefore, there will never be any issues with pick-up on these devices. (On the other hand, I suppose it's possible that there exists a device with an internal mechanism for auto-positioning the controls, but no mechanism for controlling this through MIDI. However, I seriously doubt that such a device exists.) As I said before, I think that, for now, we should simply not support non-stepwise movement of controls. We can add support for that later, but for now let's focus on getting the basic pick-up and sync working. Now, getting back to the design. If we outlaw non-stepwise movement, then there's no need to have a special mode for pick-up; we can simply have it on all the time. (In the future, it will either be on all the time or off all the time, depending on static configuration). This is the only change that I would make to your design at this point. |
From: Stephen S. <rad...@gm...> - 2007-12-30 03:41:56
|
> Okay, I will work off of master from now on. Cool. :) > Hmm... I'll look into it. That may be more git than I'm ready to learn > right off the bat, so I'll start with just working off of the master > git repo. If I'm in it for the long haul, though, it's probably the > thing to do. Fair enough. I've found that it's a worthwhile tool to learn.. These MIDI code changes are a good example; we can both implement various competing solutions and easily import each others' code to try things out and compare. In any case, if you just want to use it in a simple way, git-clone, git-pull, and git-diff are probably the only commands you need. If you want to commit changes, try making a branch off of master to make commits to. Whenever you synchronize master (git-pull), you can git-diff between your branch and mine. > Actually, I'm just going on my experience with svn (I don't know how > git works), but wouldn't it be possible to simply give me write > permissions on the master git repository? Wouldn't that be a simpler > solution? Am I simply confused? Well, I guess I have a head start on you since I've been teaching myself for the past few months. I was using subversion before that, but I like git a lot. It gives developers a lot more freedom to do what they want and exchange ideas without needing to do things like giving someone else write access to your repository. So the whole point is we can each have a repo, which live independently, but can be synchronized in an organized way. In a bigger project, yes, several devs might have push access to the main repo, but with only two programmers there's no point. I can just pull from you and stick it in a branch, and then merge what I want into the master. > I have access to a server, so that's not an issue. Cool. I may as well mention that there's also free git hosting available at repo.or.cz. cheers, Steve |
From: Stephen S. <rad...@gm...> - 2007-12-30 03:33:57
|
Hi, I'm afraid I don't have time to give you a point-for-point answer right now. I've thought about it a bit, but in fact I think a lot better about these things in C++ rather than in english, so I started coding a little to see what issues might arise. I have to thank you for making me take a critical eye to the midi code, I haven't looked at it in a while. I was horrified to find that the control codes are indexed by slider rather than the other way around.. It means each CC message received is passed through a whole series of if/else clauses-- ugly! Thinking about my suggestion for how to do it, I created a class to represent MIDI values. Each one is assigned to a control code when the configuration file is loaded, and each one has access to a GUI slider. (I had to create some base classes for the GUI sliders and buttons to abstract the Set/GetValue functionality, which I think is probably a good idea anyways..) There are two Set functions for the MidiValue class, one is SetValue() which is equivalent to your "internal" CtrlSource enum, and the other is ReceiveCC() which is equivalent to "midi" CtrlSource. Depending on which of these functions is called it will set the state of the MidiValue as NEEDSYNC or PICKUP. Anyways, this can be found in the "feature/midisync" branch in git. It's not at all complete, but should give you some idea of what I'm talking about. I'm not at all sure this is better or worse than what you suggest.. perhaps the LoobOb is afterall the right place for this stuff. However I think it's definitely a good idea to reduce the processing that occurs whenever a CC message is received, and indexing the sliders by control code is probably necessary, so I'm glad I had a hack at it. I would be interested to know what you think, and how it differs from your approach. There are only two points in your message that I think I disagree with. First is the necessity of handling this corner case where the user unplugs a MIDI cable and reattaches it. I have little interest in handing that case -- if the user is doing such a thing, he'll expect things to go strange, and a key command 's' to re-synchronize manually is probably sufficient, as we have now. Secondly, > 2. When we receive a CC message, if is exactly one tick away from the > current internal value, then we update the value. If it is not, then > we know that the MIDI slider and the internal slider have drifted > apart, and the user needs to get them back into sync before we will > respond to their CC messages. I think it is quite dangerous to assume that all CC messages will be exactly 1 tick apart. You mention yourself that it won't handle the button case -- there may be other cases where the user wants to set everything to a particular value. (Loading a preset for example.) My idea for 'pick up' was to only enable that state when a sample is loaded (i.e., the 'internal' case, a context change.) It might also be useful for when the user moves a slider, but again, this state is deterministically available to the program and doesn't depend on the difference between two successive CC values. cheers, Steve |
From: Nick T. <nh...@gm...> - 2007-12-28 04:59:36
|
On Dec 27, 2007 9:02 PM, Stephen Sinclair <rad...@gm...> wrote: > Just because I have a set coming up (new year's!) I've finally gotten > out of this two-year slump and put a bit of work into loopdub. So > even after the 0.3 release, I've made several commits. Therefore, the > last couple patches you sent, I've basically made temporary branches > off of 0.3, applied the patches, done some testing, and then moved > back to the master branch and merged the branch. Seems to work quite > well, but it would be even less work if you were working off the top > of master. (The last one I had to do some manual merging) > Okay, I will work off of master from now on. > Also, if you were to put up your own git repo somewhere, I could pull > changes from you directly instead of going through the mailing list. > Hmm... I'll look into it. That may be more git than I'm ready to learn right off the bat, so I'll start with just working off of the master git repo. If I'm in it for the long haul, though, it's probably the thing to do. Actually, I'm just going on my experience with svn (I don't know how git works), but wouldn't it be possible to simply give me write permissions on the master git repository? Wouldn't that be a simpler solution? Am I simply confused? > (We could work something out with sourceforge even, if you don't have > a server... unfortunately sourceforge doesn't have git installed, but > it actually doesn't matter since git can be used over non-git-aware > transports. It only makes pushing slightly more annoying, but for > myself I set up a post-update hook in my repo that updates the > web-hosted repo automatically when I push to it.) > I have access to a server, so that's not an issue. |
From: Nick T. <nh...@gm...> - 2007-12-28 04:47:39
|
On Dec 27, 2007 8:47 PM, Stephen Sinclair <rad...@gm...> wrote: > Hi Nick, > > I had never thought of supporting devices which can auto-position > their knobs, but what I did consider and planned on doing sometime > soon was implementing a sort of "pick up", so that when the context > switches (a loop is loaded or program is changed), and the knob and > "virtual knob" become unsynchronized, I planned on having the value > stay put until the MIDI value passes through the position of the > virtual knob, to avoid having values jump all over the place when you > touch a knob. > Yes, so I had read. These two features are not mutually exclusive, fortunately; both of them can exist simultaneously without interfering with each other. Thus, both auto-positioning and non-auto-positioning controllers will be supported in the best way possible, without any special configuration. > Committed. > Thanks! > We'll have to work out, in the future, some way of selecting a device > for CC-output and possibly a different device for clock output. > Yes, you're right. I hadn't considered that. > On the subject of device selection, I still like the simplistic little > panel of device-buttons at the top of the screen, making configuration > really fast, but as features are added, I can see that it may not > suffice for all cases. It's also sort of a waste of screen-space to > list MIDI devices that aren't in use.. it might be better to have a > single button that cycles through available devices, or something > similar.. I have yet to implement a drop-down menu, but the silly > little GUI system I devised doesn't handle overlapping areas very > well. > I like it as well, and I also see the potential need for change. One possibility would be to simply put the MIDI device choices inside .loopdub.conf. This, of course, would assume that users will want to select the same MIDI devices each time. Would you say that that is a reasonable assumption? > Actually I think it would be better to do this the other way around. > In my experience, moving more "intelligence" to the GUI is usually a > bad idea. > Yes, you're right. I presented the idea as the most obvious one, or perhaps the simplest change to the code. I do not think that it's a very good idea. > I don't really consider that the controls store the MIDI > values, they only store their own GUI-slider value, which is most > cases is the same as the MIDI-knob value, but, as you point out, can > become desynchronized. So the problem is that the actual MIDI-slider > values are not really stored anywhere... Perhaps we really need a > separate representation for the MIDI knobs. > Actually, storing the MIDI slider's current value isn't necessary, nor does it even make sense, since we can't know what the true "current" value is. We can know what CC message we last received; however, this doesn't necessarily match the slider's current value on the actual hardware controller. For instance, you could move the slider, unplug the MIDI cable, move the slider again, and plug the cable back in; now, the slider's current value does not match the value we have set for it. In a less pathological case, suppose that we have just connected the controller, and one of its sliders is in the middle of its range. The user hasn't yet moved the slider, so we don't know where it is, and whatever default value we choose for it may or may not be correct. So, in summary, we cannot store the MIDI slider's current value, since we cannot know it; we can only decide what to do based on the current internal slider setting and the individual CC messages we receive. With that in mind, we should use the following algorithm (independent of any class design): 1. When the value of a slider changes as a result of the user manipulating the GUI slider, or from an internal program setting, we send the new value to the MIDI controller. This will obviously be a no-op if the controller does not support MIDI sync. 2. When we receive a CC message, if is exactly one tick away from the current internal value, then we update the value. If it is not, then we know that the MIDI slider and the internal slider have drifted apart, and the user needs to get them back into sync before we will respond to their CC messages. This algorithm handles both MIDI synchronization and slider pick-up without any conflicts, including all pathological cases. Now, the question is: what class design is best suited to this algorithm? One thing that both the current design and your proposal miss is the notion of "the value of a slider." In the current design, the current value of the GUI slider is taken to be the correct value for the slider, which will always be true. However, once you start talking about decoupling the GUI from the rest of the program, you can no longer rely on the GUI slider to provide that information. So, any design must store the current slider value somewhere other than in the GUI slider. My proposed design puts the information in the LoopObs. Your proposed design does not put it anywhere. The other thing that my design does is provide the framework needed to implement the above algorithm, in the form of the CtrlSource parameter. For (1), whatever class initiated the change calls SetController with source = SRC_INTERNAL or SRC_GUI. For (2), in the case when the CC value is adjacent to the internal slider value, the MidiControl class calls SetController with source = SRC_MIDI to adjust the internal slider. Anyway, those are my thoughts on the subject. I think that my proposal is probably the simplest, and therefore best, way to do things; however, if you have a better way, I can still be swayed. :-) Now, just one more thing, before I forget. I mentioned earlier that I was using buttons on my MIDI controller to toggle the echo effect on and off. In detail, this is how it works. When the button is toggled on, it sends a CC message setting the feedback to 64. When it is toggled off, it sends a CC message setting the feedback to 0. If MIDI pick-up is implemented as I have described above, then it will break this scheme, since the button never moves through the intermediate values between 0 and 64. Since I personally have no use for MIDI pick-up, perhaps it would be good to have an option in .loopdub.conf to disable MIDI pick-up. But, of course, what about people with non-auto-positioning controllers who also want to use this scheme? For these people, the more general solution would be to enable/disable MIDI pick-up for individual sliders. However, this would be a rather complex thing to do for such a corner case, so I propose that we do not implement it unless somebody specifically needs it. |
From: Stephen S. <rad...@gm...> - 2007-12-28 02:03:00
|
> P.S.: The attached patch was made against LoopDub 0.3, not against the > latest git. Is that an issue? The previous patch was, as well. I ask > now only because this patch is far more invasive than the previous > one. I think it would be a good idea. I'm still somewhat learning git, but I've been getting into it a lot lately and I find it makes for a nice development environment. I don't know what your experience with it is so far, but it essentially just automates a lot of what you have to do manually when you don't use it. Generating diffs, synchronizing your version with development, creating testing branches, etc. It can even help with mailing your patches to the list. Just because I have a set coming up (new year's!) I've finally gotten out of this two-year slump and put a bit of work into loopdub. So even after the 0.3 release, I've made several commits. Therefore, the last couple patches you sent, I've basically made temporary branches off of 0.3, applied the patches, done some testing, and then moved back to the master branch and merged the branch. Seems to work quite well, but it would be even less work if you were working off the top of master. (The last one I had to do some manual merging) Also, if you were to put up your own git repo somewhere, I could pull changes from you directly instead of going through the mailing list. (We could work something out with sourceforge even, if you don't have a server... unfortunately sourceforge doesn't have git installed, but it actually doesn't matter since git can be used over non-git-aware transports. It only makes pushing slightly more annoying, but for myself I set up a post-update hook in my repo that updates the web-hosted repo automatically when I push to it.) Steve |
From: Stephen S. <rad...@gm...> - 2007-12-28 01:47:29
|
Hi Nick, > What's nice about this feature is > that it's an easy way to make sure that the controls on the device are > consistent with the controls in the software. My own controller has > this feature. That's pretty cool, mine doesn't.. ;-) You're right that LoopDub previously had support for MIDI output. I was working a long time ago on getting it to output a MIDI clock signal, but it never really worked right so I abandoned it. Then when I changed from using PortMidi to using RtMidi, the output support never got re-implemented, so this was a slight regression. (Slight because the midi output didn't really do anything useful yet..) I had never thought of supporting devices which can auto-position their knobs, but what I did consider and planned on doing sometime soon was implementing a sort of "pick up", so that when the context switches (a loop is loaded or program is changed), and the knob and "virtual knob" become unsynchronized, I planned on having the value stay put until the MIDI value passes through the position of the virtual knob, to avoid having values jump all over the place when you touch a knob. > Anyway, I have attached a patch to exploit this functionality with > LoopDub. It does two things. First, it adds MIDI output support to > LoopDub. (A lot of the infrastructure for this seems to have already > been present; perhaps LoopDub has supported MIDI output in the past?) > Second, it adds a new user interface function: when the user presses > 'S' (for 'synchronize'), CC messages corresponding to the current > values for all volume and effect sliders will be sent to the MIDI > output. Committed. We'll have to work out, in the future, some way of selecting a device for CC-output and possibly a different device for clock output. On the subject of device selection, I still like the simplistic little panel of device-buttons at the top of the screen, making configuration really fast, but as features are added, I can see that it may not suffice for all cases. It's also sort of a waste of screen-space to list MIDI devices that aren't in use.. it might be better to have a single button that cycles through available devices, or something similar.. I have yet to implement a drop-down menu, but the silly little GUI system I devised doesn't handle overlapping areas very well. > The most obvious way to do this would be > to have the slider objects themselves send the MIDI messages, but the > trouble is that they don't know anything about MIDI, being simple > user-interface objects. Actually I think it would be better to do this the other way around. In my experience, moving more "intelligence" to the GUI is usually a bad idea. I don't really consider that the controls store the MIDI values, they only store their own GUI-slider value, which is most cases is the same as the MIDI-knob value, but, as you point out, can become desynchronized. So the problem is that the actual MIDI-slider values are not really stored anywhere... Perhaps we really need a separate representation for the MIDI knobs. One thing to consider is that I hope to eventually cut a lot of the information that is shared between the GUI and the audio/midi layer. The end-goal being to eventually run them as separate processes communicating using some protocol, such as OSC. I think this would lead to better performance and better code. (I've learned a lot about multi-threading and other aspects of audio software engineering since I started loopdub a few years ago, and one thing I've learned is that threading is, in general, a bad idea. Unfortunately it's all over the place in loopdub.) So, with that in mind, I think we should do something similar to what you propose, but instead of making the LoopOb more intelligent, we should create a class representing a MIDI knob which lives within the MIDI-oriented code (ld_midi), and which knows how to synchronize with particular GUI sliders and also knows when to re-sync the real knobs or go into "pick up" mode. With the intelligence in the MIDI code, there will be no need for the CtrlSource enum. Knob values sent from the GUI (by mouse movement or context change) can be directed to the output device (and put the knob in "pick up" mode), and knob values received by MIDI input can be directed to the GUI. These will be in two distinct places in the code. If I'm correct, no feedback loop should occur. Steve |
From: Stephen S. <rad...@gm...> - 2007-12-27 23:47:42
|
On Dec 26, 2007 5:08 AM, Nick Thomas <nh...@gm...> wrote: > There are a couple defaults in LoopDub that I don't like. The default > button mode is cue, where I would like it to be hold, and the default > loop volume is 100%, where I want it to be 0%. So I was thinking that > maybe this sort of thing should be configurable. I've attached a patch > which implements another configuration file, .loopdub.conf, which > contains this sort of general configuration information. The two > things I mentioned, default button mode and default volume, are the > only configuration parameters that I've implemented. Anyway, tell me > what you think of this idea. Good stuff, I committed it. (This time I figured out the --author option for git-commit.) I'd been toying with the idea of making the volume sliders default to 0 actually, but this resolves it for me. Thanks, Steve |