Traktor track name / time to LCD via MIDI! ...using Denon LCD support & Arduino
Home :: Reviews of DJ equipment :: Traktor track name / time to LCD via MIDI! ...using Denon LCD support & ArduinoReply
Traktor track name / time to LCD via MIDI! ...using Denon LCD support & Arduino Posted on: 15.04.2011 by Lillia Mestdagh Hi AllThis has already been discussed in another thread however it was decided that it was probably a good idea to put the info in a new thread. Firstly.... here it is in action! http://www.youtube.com/watch?v=9gQBgCKsGgc Here is the info I posted about how its done... By using the MIDI outputted for the Denon HC4500. When you add a HC4500 to your list of controllers, Traktor will start to output MIDI for the track name, artist and time. Its not an option you can select in the 'add out' section in Traktor, it happens in the background as soon as you add the DN4500 controller and select a MIDI OUT port. I used the Denon MIDI sheet to get the info Here is the sheet I used, Denon MIDI (page 7) : HC4500 MIDI Command List As only 7 bits of the MIDI data messages are available (the first bit is used to identify the message type) and the LCD needs 8 bits of data to display a character, each character needs to be transmitted in two control change messages. The first bit is used to idenfify the message, nothing to do with LCD but will be used in your code by the MIDI IN routine. The next three bits are discarded, and the final 4 bits are used for the data. The first control change message contains the first 4 bits of the 8-bit LCD character data, and the second CC message contains the second 4 bits, so.... X000AAAA + X000BBBB = AAAABBBB Where X is the message identifier bit, the '0s' are discarded, A is the first CC and B is the second CC. Assuming you have Arduino sucessfully receiving MIDI CC, by loading two CC messages into cc_data1 and cc_data2 the following code is a simplified way of getting the MIDI messages to the LCD. The actual code uses bitwise (see arduino website) to join the two nibbles together and simplified looks like this... This line shifts the first 4 bits of the first message along 4 places to make 0000AAAA into AAAA0000 lcd_nibble1 = (cc_data1 << 4); This line takes the data from the second CC message and passes it to a variable for the LCD routine lcd_nibble2 = cc_data2; Now we have the following lcd_nibble1 = AAAA0000 lcd_nibble2 = 0000BBBB Now we need to merge the two using the bitwise OR operator... lcd_output = lcd_nibble1 | lcd_nibble2; so now 'lcd_output' is AAAABBBB, a complete byte which can be passed straight to the lcd.print command using the standard Arduino LCD library... lcd.print(lcd_output); Now this code could be better as the library will break the byte up back into nibbles to pass to the LCD using the 4-bit interface (as my design uses 4-bit connection) so when I get some time, ill most likely make a few mods to the library to save some considerable processing time! However at the moment in development, this method works great and is a good way to simply use the standard Arduino LCD library in 4 or 8 bit mode. There is one more thing, I described how to pass the CC data to the LCD but nothing about CC numbers. The value of the CC message relates to the character but the CC number determines both the character position and identifies whether the message is the first or second nibble of data. Its all in the Denon MIDI sheet. For example.... If you (or Traktor!) wanted to display the letter 'A' in the second (of 16) character position and on the first line you would use the following... The character 8-bit code (from Denon or Hitachi LCD datasheet) is 0100 for the first nibble and 0001 for the second nibble, so... CC message 1 = 0001 = 1 (in decimal) CC message 2 = 0100 = 4 From the Denon sheet, CC number 2 (0x02 in hex) represents the first nibble for the second character on the first line of the display. CC number 34 (0x22 in hex) represents the second nibble for the second character on the first line of the display, so... CC#02 value 1 CC#34 value 4 will display the letter 'A' in the second char position on the first line. BTW Deck A will output all this info on channel 1 and Deck B will output it on channel 2... so my advice if your designing a controller with the Denon LCD system, reserve ch1 and ch2 for the LCD data! Here is the actual code with bits removed that dont relate to the LCD (easier to understand! ), please note the MIDI channel is currently ignored but a simple if or switch statement could be included to check the channel is correct or identify whether the data is from deck A or deck B, just havent got round to doing it yet! to use this code the receiveMIDI routine is fired whenever the serial port data is read and verified to be a recognised MIDI message. The following variables must be passed to the routine... statusType = type of message, CC, note on, note off etc... MIDIchannel = self explanatory! param1 = first parameter of data (for CC this would be the CC number) param2 = second parameter of data (for CC this would be the CC value) Code:
void receiveMIDI(byte statusType, byte MIDIchannel, byte param1, byte param2){ switch (statusType) { break; case 0xB0: ///// IF MESSAGE IS CONTROL CHANGE MESSAGE (0xB0) ///// switch(param1){ // CHECKS CC NUMBER, MSB GETS PUT IN tn_byte1 case 0x01: tn_byte1 = (param2 << 4); break; case 0x02: tn_byte1 = (param2 << 4); break; case 0x03: tn_byte1 = (param2 << 4); break; case 0x04: tn_byte1 = (param2 << 4); break; case 0x05: tn_byte1 = (param2 << 4); break; case 0x07: tn_byte1 = (param2 << 4); break; case 0x08: tn_byte1 = (param2 << 4); break; case 0x09: tn_byte1 = (param2 << 4); break; case 0x21: // BEGIN LSB, MSB IS READY IN tn_byte1 tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(0 , 0 , tn_output); // FIRES LCD PRINT WITH CO-ORDS AND CHAR DATA break; case 0x22: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(1 , 0 , tn_output); break; case 0x23: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(2 , 0 , tn_output); break; case 0x24: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(3 , 0 , tn_output); break; case 0x25: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(4 , 0 , tn_output); break; case 0x27: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(5 , 0 , tn_output); break; case 0x28: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(6 , 0 , tn_output); break; case 0x29: tn_byte2 = param2; tn_output = tn_byte1 | tn_byte2; track_name(7 , 0 , tn_output); break; } } } void track_name(byte lcd_col, byte lcd_row, byte lcd_data){ lcd.setCursor(lcd_col , lcd_row); lcd.print(lcd_data); } Here is the post about the board itself and the spec im aiming to achieve... * Arduino based design using ATMega168 (or 328) with on-board MIDI I/O port * 48 Analogue / Digital inputs or outputs (6 ports with 8 pins, each can be either I or O) by use of on-board multiplexers * Built-in twin 8-LED bargraph VU meter, controlled by MIDI CC * 8x2 (or 16x2 if you want) LCD display * Menu system allows for changes without reprogramming, so Arduino is optional, the MIDI config can be changed with the LCD menu * Supports the display of Traktor track name, artist and time on the LCD display (Uses/hijacks the data Traktor sends out for the Denon HC4500 LCD display) There is no built-in FTDI chip like there is with the Arduino boards however there is a connector for an FTDI programmer, I use the Modern Device USB-BUB, http://shop.moderndevice.com/products/usb-bub, the little red board shown in my picture below Im keen to get some feedback about whether peeps are interested in this kind of product aimed specifically at Traktor or Ableton. This is only a prototype board meant for testing all the features, so it looks a bit of a mess! Please excuse rubbish mobile phone camera pictures too! | |
Arcelia Siebeneck 17.04.2011 | in that case, any custom arduino hardware being designed for commercialisation should perhaps take this into consideration. It's worth the added cost imo. I personally don't believe Arduino-based scrolling in a 12 segment window is much of a problem as the remaining 4 segments could be used for other things (like time or a deck indicator). It's just the scrolling via midi which I'm not such a fan of - why on earth did NI design it this way?! |
Louisa Oberc 16.04.2011 | Well I can't seem to get a complete track name.. The major issue at hand right now is that the 'window' is only 12 characters long, so if a track name is longer than 12 characters, I really have no way to figure out where the 13th character should go (since the character will be different, yet the segment would be the same)... I believe that if I were to use something like this in a controller, a dedicated processor would likely be the best way to handle it... especially because in TP2, the midi is streamed twice as fast, taking even more processing away from more important things. |
Louisa Oberc 16.04.2011 | Scratch pad of my findings: Midi out -> Transport -> Play/pause: will output upon play/pause (duh..) will output pause state if you change tracks while the deck is playing (deck b playing, load new track in deck b while deck b is still playing..), will NOT output if track is loaded while deck is paused. Midi Out -> Load -> Unload: Cannot seem to get it to output anything... ever.... Midi Out -> Transport -> Cue: Out puts when cue is pressed, nothing during track load Midi Out -> Load -> Load Selected: So far this one seems to be the winner with one exception and one quirk. For some reason it sometimes sends multiple note-on messages, but as far as I can tell, it only sends a single note-off per load. However, it WILL NOT output when you drag and drop a track, only when you right click and select 'load track in deck x'. I tested it with a controller and it works the same way... Conclusions... I'm going to further investigate this using the Load Selected output... so far it seems to be the only stable way to know when a track as been loaded. The downside is that it wont work if you drag and drop a track into a deck... |
Lillia Mestdagh 16.04.2011 | Wow, some serious brain power being applied to this at the mo by you guys I believe im getting addicted to this community
!
We could approach this in a slightly different way. Traktor doesn't output midi when a track changes but there's nothing to stop us from creating some midi data output ourselves upon track change
http://www.native-instruments.com/fo...ad.php?t=97987
The ideal solution wouldn't require any further config, but I don't see any other way around it.. Great idea..
I know Denon TSI has the Denon function names instead of CC numbers but we could always just assign the 'load track midi out' to say for example 'Deck A > Cue' and then look in the Denon MIDI sheet to find out the MIDI CC of this Denon function to use in the Arduino code. I would have also thought that it would be more straight forward for an end user to just import a downloaded TSI because if you try and explain that they have to create a HC4500 TSI and leave it blank there is always going to be someone who cant get it to work because they have created a Generic MIDI one instead or someone else who will be confused because they have to leave the TSI blank... it confused me for a while as to why the LCD was working with no MIDI out listings in the TSI!! |
Louisa Oberc 16.04.2011 | The ideal solution wouldn't require any further config, but I don't see any other way around it.. Great idea.. I'm headed to bed, but I'll take a look and see what midi outputs for track loading are available, I'm sure there is something... Once I know a new track is loaded, I believe I can figure out a way to assemble the string... but I am certainly open to suggestions |
Arcelia Siebeneck 16.04.2011 | We could approach this in a slightly different way. Traktor doesn't output midi when a track changes but there's nothing to stop us from creating some midi data output ourselves upon track change. For example, there could be 4 midi buttons on the controller that are used to load the currently selected track in the browser into one of the 4 decks. When this buttons is pressed the following happens: - The Arduino listens out for this particular midi CC and uses this as a trigger to start listening for title/track text. - The currently selected track is loaded into the corresponding deck. - The Arduino stops listening for the title/track text after a certain period of time, it detects double spaces and/or a text loop is detected. - The Arduino continues to display this text on the LCD screen until it detects this same midi command again. Using this method we don't need to use the 00:00 time detect method so it won't matter if Traktor doesn't output this all the time. The only problem is the text looping issue. Here are some of my (slightly hacky) solutions: 1) Use something like Tag&Rename to add a special symbol to the end of the track title and artist name on every mp3 file on your computer. The Arduino then listens out for this symbol (or combination of symbols/characters) and then uses this to detect where the end of the text is. You could also set the Arduino not to display these symbols/characters. 2) If we now have a 'concrete' way of telling when a new track has loaded (by using the midi button method above) then we could look at the array solution again perhaps? It's a little bit beyond my coding abilities but I grasp the concept. Thoughts? |
Louisa Oberc 15.04.2011 | Well guys... I don't believe that this can be done reliably
Reasoning: 1) If we use time=0 type of logic, the display won't update until you start playing the track 1) As per Mil0, not everyone starts at the beginning of the track 1) I thought detecting a large variance between values of the track position value (percentage from 0-100), but that won't work if the starting position is within the threshold; it won't update.. 2) This would have been a great help 3) Detecting where the track name starts and ends would be near impossible, we have double spaces, but some tracks may have spaces at the end of the tags, and I'm not sure how reliable that would be. Initially I was believeing to store the track name by filling in an array based on the character and segment, but each time the data gets received the letter will be different and the segment the same (since it's scrolling), the only way I can see it working is if we have a CONCRETE way of telling when a track has been changed... Deducing a change from track names would be nearly impossible.. As far as my programming ability at least Using combinations of techniques may increase the reliability, but at that point, I'd say that dedicating a microcontroller for the displays would be easier and more efficient... I'd likely use it to control the leds on the controller as well, so it wouldn't be a total waste. Please, I beg you guys... prove me wrong! |
Lillia Mestdagh 15.04.2011 |
Originally Posted by DjNecro
With regards to the font table, dont forget we are not using the HC4500s 'actual' LCD module nor are we using the DNS3700s 'actual' LCD module, the font table to look at is not in the Denon MIDI sheets but in the datasheet for the LCD display being used. Any problems with incorrect characters will be due to the LCD module connected to Arduino. 12 / 16 characters should not pose too much of a problem either. If you wrote code to try and receive on all CC numbers for segment 1 - 16 (from DNS3700 sheet) you would only see track and artist being displayed on segs 1 - 12. If you used a smaller display than 12 segs then you get my 8x2 display above!
Originally Posted by DjNecro
Originally Posted by DjNecro
...I have however been stroking my chin and been looking into modifying the FTDI driver to possibly pipe MIDI over USB a little quicker than normal! Im sure modifying the driver to work as a MIDI driver is possible and the standard MIDI baud rate can be achieved, im not sure about running it quicker than normal though, another project for another time I believe! |
Arcelia Siebeneck 15.04.2011 |
Originally Posted by Siytek
Regarding checking when a new track loads so that the text updates - there must be some midi that gets triggered or outputted when a new track starts playing or is loaded. Having the Arduino listen out for that would trigger it to display the new text. Otherwise, waiting for 00:00 might be a problem as some people use Load beat markers which mean the track gets loaded into a deck at a different time from 00:00. Finally, regarding using more than one LCD screen - totally agree! My controller is built around two x 16x2 LCD screens. I truely believe that this is one of the last major obstacles in building a professional DIY Traktor midi controller. I'm really excited by what you and djnecro have managed to achieve so far - can't wait to see how this pans out Speaking of which, I'd happily pay ~ |
Louisa Oberc 16.04.2011 | I was going to do some inline quoting but I am running late for an appointment... Regarding the pdf you are using... I highly recommend changing the code to work with the pdf I posted (attached to this post)... Traktor specifically supports the hc4500 (with its 12 segment display), I'm not sure if using the 3700's midi-spec will cause a problem in the future (or with certain charcters since the 3700's font table is slightly different than the hc4500's). I was doing some believeing about how to stop the scrolling (which is about twice as fast in TP2 )... Your idea about the double spaces intrigues me... I will have to play... combining that with the track time (which I havent stripped out of the midi data yet) may be the trick we need to make it work... The first thing I believe should be left out of the code would be the frame (?) number... processing and displaying the frames (of which there are many many per second) will add a crap-ton of extra processing time... If I were to have two in my controller I would be believeing of dedicating a board and chip to drive the displays due to the processing required... the last thing we want is latency on the midi out (which is the only thing that really matters). |
Lillia Mestdagh 16.04.2011 |
Originally Posted by MiL0
Originally Posted by MiL0
I have wondered about stopping the constant MIDI processing to keep this info on the screen, it is processor hungry for what it achieves! I figured you could identify the end of the track name or artist by the fact that there are two spaces at the end, this would allow the whole track name or artist to be loaded into the Arduino at the speed Traktor scrolls it (the info could scroll on the screen and stop, when it stopped so would reading the MIDI). The problem I believe is once you have this info, you can ignore the MIDI data relative to the track name and artist, the difficult bit is getting the Arduino to know when the track is changed. Hmmmm..... im believeing as I type.... maybe some connection with the mm:ss:ff might do it? ie Arduino checks to see if the track name has changed when the timer is put back to 0:00:00, ie when you load in a new track!
Originally Posted by MiL0
|
Miquel Catan 15.04.2011 | While I'd never do this myself. I believe its awesome to see people take the initiative to do stuff like this. Awesome ideas and implementation. Awesome just to read and see how people go about stuff even if I don't understand all of it. |
Lillia Mestdagh 15.04.2011 |
Originally Posted by extraclassic
Im guessing for yourself extraclassic, the fact that your part of the djranking s community and seem interested in something as geeky as my Traktor LCD project would suggest to me that you have all the tools necessary to embark on the journey of learning Arduino! |
Arcelia Siebeneck 15.04.2011 | amazing work... welcome to the community
by the way! one thing that I've noticed is that Traktor seems to output the track name and title constantly. It also seems to scroll the text, rather than output the entire length of the track/title and let the controller do the scrolling. The disadvantage with this is that the scrolling looks a bit choppy (and will likely get worse if a lot of midi messages are being sent/received). I believe a better method would be to write some code that extracts the whole track name and artist name and then outputs it once. Further code could then be written to let the Arduino deal with scrolling the text, the speed it scrolls or just keeping it stationary. I intend to do the same thing with the Autohotkey script I'm writing (for non-Arduino users). BTW - have you seen my VU meters thread? check my sig for details... might save you a bunch of LED outputs on the Arduino if you do it that way. You could then have the VU meters, track title, artist and time remaining all being shown on an LCD display (with a midi button to change what's being displayed?) |
Leeanna Ayla 15.04.2011 | Fantastic post. I'm attaching the pdf to the thread so if it goes away from the Denon site for some reason we'll still have it. |
Tatum Ansaldo 15.04.2011 | very cool, thanks for posting. |
Joan Kollmorgen 15.04.2011 |
Originally Posted by Excluded
Siytek what's the learning curve like for programming the Arduino? For a complete noob like me that's never programmed anything in his life? |
Daniele Gladys 15.04.2011 | sick mate wish i was technical to do this stuff aswell ! |
<< Back to Reviews of DJ equipment Reply