Jump to content

audiocommander

Frequent Writer
  • Posts

    1,358
  • Joined

  • Last visited

Everything posted by audiocommander

  1. sure, these are some snippets, that should illustrate how it works; it's not very cleaned up :-\ #pragma mark - #pragma mark m4 time intervals #define ZSTIMEINTERVAL_MAX 11 // timeinterval = ( 1 / INTERVAL ) * 96 #define ZSTIMEINTERVAL_1 96 #define ZSTIMEINTERVAL_2 48 #define ZSTIMEINTERVAL_2T 36 #define ZSTIMEINTERVAL_4 24 #define ZSTIMEINTERVAL_4T 18 #define ZSTIMEINTERVAL_8 12 #define ZSTIMEINTERVAL_8T 9 #define ZSTIMEINTERVAL_16 6 #define ZSTIMEINTERVAL_16T 4.5 #define ZSTIMEINTERVAL_32 3 #define ZSTIMEINTERVAL_32T 1.5 @interface ZSMidiClock : NSObject { PYMIDIManager *pyManager; PYMIDIEndpoint *port; NSMutableArray *notifiers; BOOL isMaster; BOOL signal; unsigned int signalCounter; unsigned int clock; // counts from 1 to 96; // %1 = 96. // %3 = 32. // %6 = 16. // %12 = 8. // %24 = 4. // %48 = 2. unsigned int timeStamp; // AudioGetCurrentHostTime() or from receivedClock float tempo; // for master-mode unsigned int barFactor; // tempo/60*2.4 unsigned int bar; // number of bars unsigned int currentBar; // current bar related to denominator unsigned int numerator, denominator; // eg: 4/4 BOOL debugMode; } @interface ZSMidiScheduler : NSObject { ZSMidiClock *mc; unsigned int timeIntervals[ZSTIMEINTERVAL_MAX]; // eg ZSTIMEINTERVAL_1 ... NSMutableDictionary *knownDestinations; struct ZSMidiMessageQueue queue[ZSQUEUE_MAX]; // see ZSMidiBasics for struct definition! // 32 * 3 (32.note) = 96 // the queue schedules events by bars, // NOT timecode :) BOOL debugMode; } #pragma mark SCHEDULERS -(void)scheduleMsg:(Byte*)msg quantizedFor:(int)interval // see ZSTIMEINTERVAL withLength:(int)length forDestination:(id)destinationObject { // if no clock is available, messages should be sent right away // ... // new message struct ZSMidiMessage scheduledMsg; unsigned int timeUnit = interval; // send NoteOn asap, noteOff after 'length' if(isNOTE_ON(msg[0])) { // schedule corresponding NOTE_OFF if(length > 0) { unsigned int noteOff = ((int) MIDI_NOTE_OFF) + channelOfMessage((int) msg[0]) - 1; Byte noteOffMsg[] = { noteOff, msg[1], msg[2] }; unsigned int newInterval = interval + length; if(newInterval > 96) { newInterval = newInterval % 96; } [self scheduleMsg:noteOffMsg quantizedFor:newInterval withLength:0 forDestination:destinationObject]; } } //scheduledMsg.timeStamp = [mc timeStamp] + ( 1 / length * 96 ); scheduledMsg.message[0] = (unsigned int) msg[0]; scheduledMsg.message[1] = (unsigned int) msg[1]; scheduledMsg.message[2] = (unsigned int) msg[2]; scheduledMsg.destinationID = uniqueZSID; // add to queue unsigned int numberOfEntries = queue[timeUnit].numberOfEntries + 1; if(numberOfEntries >= ZSQUEUE_MAX) { NSLog(@"queue is full. resetting queue...\nplease increase ZSQUEUE_MAX"); // reset queue [self resetQueue]; return; } queue[timeUnit].numberOfEntries = numberOfEntries; queue[timeUnit].ZSMidiMessages[numberOfEntries - 1] = scheduledMsg; // debug if(debugMode) { NSLog(@"Msg queued: %i for %i ->Destination: %i", scheduledMsg.message[0], timeUnit, scheduledMsg.destinationID); } } #pragma mark CLOCK RECEIVER // after registering @ mc this is called 96 times / bar -(void)receiveClock { _Bool tester; unsigned int timeUnit; unsigned int n; for(n=0; n<ZSTIMEINTERVAL_MAX; n++) { // eg: all "24" events get fired if clock is "0/24/48/72/96" // => 48 % 24 = 0 => also passt intervall 24 tester = [mc clock] % timeIntervals[n]; if(tester != 0) { continue; } else { timeUnit = timeIntervals[n]; } if(queue[timeUnit].numberOfEntries > 0) { // build packets Byte msg[3]; int destinationID; id destinationObject; NSString *key; unsigned int i, j; for(i=0; i<queue[timeUnit].numberOfEntries; i++) { // prepare outPacket MIDIPacketList outPacketList; MIDIPacket *outPacket = MIDIPacketListInit(&outPacketList); for(j=0; j<3; j++) { msg[j] = queue[timeUnit].ZSMidiMessages[i].message[j]; } destinationID = queue[timeUnit].ZSMidiMessages[i].destinationID; key = [[NSNumber numberWithInt:destinationID] stringValue]; destinationObject = [knownDestinations valueForKey:key]; if(destinationObject == nil) { // reset queue [self resetQueue]; return; } else { unsigned int msgLength = lengthOfMessage(msg[0]); unsigned int timeStamp = [mc timeStamp]; outPacket = MIDIPacketListAdd(&outPacketList, sizeof(outPacketList), outPacket, timeStamp, msgLength, msg); // send packetList [destinationObject performSelector:@selector(processScheduledMIDIPacketList:) withObject:[NSData dataWithBytes:&outPacketList length:sizeof(outPacketList)]]; } // debug if(debugMode) { NSLog(@"Msg sent: %i @ %i", msg[0], timeUnit); } } // remove sent messages from queue queue[timeUnit].numberOfEntries = 0; } // loop next possible interval... } } #pragma mark - #pragma mark ACTIONS // action methods // message receiver -(void)processMIDIPacketList:(const MIDIPacketList*)inPacketList sender:(id)sender { if(! isMaster) { // receive clock 0xF8 const MIDIPacket *inPacket; unsigned int i, j; // loop packets for(i=0; i<inPacketList->numPackets; i++) { inPacket = &inPacketList->packet[i]; timeStamp = (unsigned int) inPacket->timeStamp; // loop messages for(j=0; j<inPacket->length; j+=2) { switch(inPacket->data[j]) { case MIDI_CLOCK: clock++; if(clock > 96) { clock = 1; } signalCounter++; if(signalCounter >= 24) { signal = YES; signalCounter = 0; // update bar bar ++; } case MIDI_START: clock = 0; bar = 1; break; case MIDI_CONTINUE: clock = 0; bar = 1; case MIDI_STOP: clock = 0; bar = 1; break; } } } } } Michael :)
  2. Hey, that's great! if anybody is generating a 3d-view of a MBHP-module, will you upload it to the wiki? that would be wonderful! :D cheers! Michael
  3. Hi simone! AFAIK you can control from 20.00 up to 999.99 bpm. If you're assigning your remote MIDI controls and have the tempo button activated, look at the bottom of the Live-Window. Choose "absolute (14-bit)" there and you can set a 14bit tempo there. I think you have to refer to the official MIDI-CC-tables to get the corresponding CC-MSB and -LSB Controllers (see wiki->midi). With 14-bit control you can also assign cents (just tried that) :) Cheers! Michael
  4. LOL ;D Maybe it's because it's slightly unlogic... I overlooked that I want to schedule also generated NoteOff events, which would be complicated this way; the idea behind this was not to generate a lookup array (fire event in buffer at time x), rather than a few simple buffers (like drawers), where you just sort out the events (sort into drawers) and fire the event (empty the drawer) when it's time... In other words: the current implementation (objective-c) uses modulus operators and a multidemensional array and consists therefore of a ridicilously low number of lines... but I see some problems in implementing for MIOS: - no huge arrays - no modulus (at least not cheap to have) - problems with nested, more-dimensional arrays okay, I think, I need to go to bed, before I'm confusing myself ;D Cheers! Michael (see you at #midibox @efnet?, 've been there today :) )
  5. Yeah, I appreciate talking about that stuff, I always feel like I got some holes in my brain whenever I try to think four-dimensional ::) Hm, at first, I'd have to decide how accurate everything should be. Because my personal encouragement is to do indetermined live-music, I'd prefer a simple solution and not one where I can fire thousands of notes in complete predetermined accuracy... if you know what I mean ;) Keeping some bytes for other things would be nice... Next, we need to think about what to store. If we schedule midi messages, we need to store at least three different numbers: type+ch, pitch, velocity... that doesn't help to make things easier... It would be nice to be able to store all kinds of messages (eg. also PRG-CH, CCs as well as Note-offs) and not only note-ons... So, what about the timing? The MidiClock signal is sent 96 times per bar. How does that look practically: 1/1 = 96th (1 time) 1/2 = 48th (2 times) 1/4 = 24th (4 times) 1/8 = 12th (8 times) 1/16 = 6th (16 times) 1/32 = 3rd (32 times) so, we can't use 1/64's anyway, because we would need to determine 1.5 clocks and – to be honest – that's a bit too much pain in the a** to me for a thing I am not able to hear... at least when one's not jamming at 20 bpm ;D haha... what an exiting jam! :P then we got the uneven notes: 1/3 = 36th (3 times) 1/6 = 18th (6 times) 1/12 = 9th (12 times) So, there would be 9 arrays in total + 2*9 arrays for the corresponding pitch/velo information. Would be 27 arrays... uff... Anyway, another advantage would be, that the 1/1 array can be really small, whereas the maximum available length for arrays should be more than enough for the 1/32 array... But not finished here: I'd introduce 9 vars to keep track of the current fill-status (option 1). E.g. if there are 4 1/16 notes in the buffer, the var contains a 4, so that we know we can access index 0 - 3 when the firing-time is there. Afterwards we can set this var to 0. Another option (option 2) would be to fire only if the value > 0 and set the value to 0 afterwards. This would require to loop through the whole array each clock which might be not the most elegant solution, so I'd go for option 1. Besides we would exactly know where to add new buffer-elements, when there's a tracking var available. And we'd know when the buffer is full and deny further elements. I'd do all the scheduling whenever a message is received. The parameters (why what is scheduled in which array can be setup independently from the HUI and is worth another much too long post ;) What do you think? Best, AC
  6. That's exactly what I'm currently developing ;D ...but I'm not planning to build it as Master Box, but rather as Slave, so the Signals are being passed when there's no clock-signal available and quantized when a signal is detected (the detection already works). I'm also planning to implement a function that converts CC#s to Notes, because the Quantisation provides a method to implement lengths of notes that is needed to send the appropriating note-off signals. I already checked out all the clock-stuff, but still need to think about the event-buffer. I programmed this already on the mac (Objective-C), and used a lot of pointers and arrays there, but I think MIOS needs kind of different approach to that... Cheers :D Michael
  7. Hi Adept74, this topic has been brought up some times, please search again the forum for it. Twin-X posted one link some while ago: http://www.midibox.org/forum/index.php?topic=6546.msg41250#msg41250 But AFIK there's not much available for the PIC and no (or at least no easy usable) free sim. Regards, Michael
  8. You could upload the ain64_din128 app; I think it shows what din button is pressed: http://www.ucapps.de/mios_download.html There are also test-applications to check encoder settings. Is that what you were looking for?
  9. sure, you're setting PORTB = card_l_addr; SRAM_LAT_LATCH1_LE, SRAM_PIN_LATCH1_LE PORTAbits.RA0 = 1; SRAM_LAT_LATCH1_LE, SRAM_PIN_LATCH1_LE PORTAbits.RA0 = 0; PORTB = card_h_addr; SRAM_LAT_LATCH2_LE, SRAM_PIN_LATCH2_LE PORTAbits.RA1 = 1; SRAM_LAT_LATCH2_LE, SRAM_PIN_LATCH2_LE PORTAbits.RA1 = 0; TRISB = 0xFF; SRAM_LAT_CS, SRAM_PIN_CS PORTAbits.RA2 = 0; SRAM_LAT_OE, SRAM_PIN_OE PORTAbits.RA5 = 0; ram_byte = PORTB; SRAM_LAT_OE, SRAM_PIN_OE PORTAbits.RA5 = 1; SRAM_LAT_CS, SRAM_PIN_CS PORTAbits.RA2 = 1; TRISB = 0x00; return; } Comments with '//' are just until a new line begins. Or am I overseeing something ??? This is so obvious, I'm a bit irritated :-\ I do also wonder, why these lines don't produce a compile warning: SRAM_LAT_LATCH1_LE, SRAM_PIN_LATCH1_LE PORTAbits.RA0 = 1; Cheers, Michael
  10. sorry, don't know where to get these. I think, you will know already most of my supplier's linklist, but maybe there's one you'll find those... http://www.alltronics.com/ http://www.bb-elektronik.de/ http://www.bilex-lp.com/ http://www.ledtronics.com/ http://www.elfa.se/ http://www.excesssolutions.com/ http://www.farnell.de/ http://www.heldt-electronic.de/ http://www.hvwtech.com/ http://www.mellesgriot.com/ http://www.olimex.com/ http://www.pollin.de/ http://www.reichelt.de/ http://www.rjselectronics.com/ http://www.shop.robotikhardware.de/ http://www.rsonline.de/ http://www.sander-electronic.de/ http://www.distrelec.com/ http://www.sparkfun.com/ http://www.voti.nl/ http://www.westfalia.de/ good luck ;D Michael
  11. void SRAM_Read(void) __wparam { //movff SRAM_ADDR_2, _PORTB PORTB = card_l_addr; well, afaics there are no asm-fuctions active, you're just setting some vars over and over again... although this should not be the main problem, I'd say it smells a bit cheesy ::) :) That may really help! The SDCC generated files contain a lot of comments and are useful even for ASM-idiots like me! ;D yes, this can easily happen. If you have an overflow somewhere, which can very easily happen, f.ex. if you're assigning an int value to a char without proper declaration, it is quite probable, that the remaining bytes will overwrite some other data and therefore produce nearly unpredictable strange results. And - I don't have exact knowledge about the inner life of MIOS or the PIC - but there are Interrupt Service Routines (ISRs) active... so I could imagine, that some strange things can happen when you're trying to run a very long nested function, esp. if you're dealing with common MIOS vars like PORTAbits.RA0, that might (! might, I have no clue!) be in use somewhere else... This will be more relevant the more code you have in your program. In your case, I would first try to comment out all function calls (esp. the SRAM_Read) and see if the general structure of the loop works; maybe in a fresh project, where you can roule out the possibility of having an overflow situation somewhere else. If I were you, I'd also try to reduce the number of function calls to a minimum amount (inside the loops); and I would add an unsigned char buffer[64], fill that buffer and write it as a page when it's filled. You can find some examples in the function reference list. That should also speed up things! It would be interesting if that behavior will remain if you optimize the loops... best regards, Michael
  12. ...and here are two links not Midibox-related, but might be of interest for you :) if you'd had a mac, I could give some more ;D http://www.speech.cs.cmu.edu/ http://www.speechandhearing.net/laboratory/tools.html
  13. http://www.midibox.org/dokuwiki/doku.php?id=midibox_speakjet I'm just about to finish this little application for total midi-control ;) cheers! Michael
  14. Hi jackchaos, what target do you compile? are you using the ACSim classes? maybe Code::Blocks is using GCC and not SDCC, this would explain this error... hard to say :-\, can you give some more informations? cheers, Michael
  15. Hi ilmenator, first, it could be interesting what happens here: SRAM_Read(); error |= MIOS_BANKSTICK_Write(bankstick_addr, ram_byte); have you declared these three variables as volatile? I remember I had various problems before I did so. See the Wiki->C Tipps&Tricks for info on volatile... You mention, all three get modified at various places; can it be they get modified while this codesnippet is being processed? Where do you have that code, is it in an ISR; is there a timer that changes any of these three values? have you taken a look in the generated .asm file in the /output directory? sometimes one can find a valueable hint there. regards, Michael ps: I doubt it has something to do with your problem, but if you'd use MIOS_Bankstick_WritePage you'd save 64 function calls. TK told me once this is a lot faster than writing single bytes.
  16. can you give some more information? "don't work" is a term I hear often, but not really useful to provide help... do you have an LCD? what does it say? what program are you using to upload the files?
  17. if you want to convert a MIOS .hex-file, you need to give the pearl script some extra startup informations (start parameters), so it knows it can write to some special protected areas. This is a security function, because it is inteded for applications. It's recommended to upload MIOS with MIOS Studio that can send .hex files, so you do not need to convert it. However, if you need to convert it to .syx see the comments in the perl script. Cheers, Michael
  18. it should work with 10.4.8. and plumstone without any problem! but things are different for 10.3.9; you'll need a java-update and tweak some settings like you can read one (1) page before this: http://www.midibox.org/forum/index.php?topic=5230.msg41214#msg41214 regards, Michael
  19. snaper, have you seen this image, when you downloaded the internet ;D ? I think this explains it pretty well. If you think of a computer, MBHP is the Hardware (Mainboard, Soundcard etc...), MIOS is the Operating System (it's called the Midibox Operating System, therefore the name) and on top of this are the applications like the MB64(E), MBSID, MBSEQ and so on... Of course you just have to upload once. Like it's with your Computer, you don't need to put on a new system when you're installing an application and once you shut it down, you can still start it without having to reinstall ;) cheers, Michael
  20. have you installed plumstone? I have 10.4.8. and plumstone and it works perfect for me!
  21. ??? sorry, I don't know what you're talking about. The PDF clearly shows 32 DINs, 2 Grounds and the connections to the Core. You seem to make it more complicated than it is. You should already have the right Java Runtime on 10.4.8 But you need Plumstone, a MIDI extension for Java. I assume you haven't installed that, right? Go to the Startpage of this Forum, look into "Miosstudio" and find the first fat sticky thread called MIOSStudio for Mac Users
  22. quote from http://www.ucapps.de/mbhp_din.html : How to connect 32 buttons: http://www.ucapps.de/mbhp/mbhp_dinx4_32buttons.pdf If you are interested in a particular answer to a question, you should first read the most obvious relevant pages @uCApps.de, at least the one of the module you're asking about ;) ;) Cheers, AC
  23. I'm sure you mean a = 2 * 512, then it's correct and you'll save a lot of codespace and calculating power this way ;) Cheers! Michael
  24. The KP1 is 75mm x 100mm (visible area). Cheers, AC
  25. :o allright, now you got my full attention ;D that seems like a great list with 80% of my idliketobuildsomethinglikethisinthefuture-projects!!!
×
×
  • Create New...