Welcome to xLights Sequences

A modern, easy to navigate, simple to use site to share your very own created xLights Sequences.
Not only that, we offer a marketplace where you can sell your own sequences or showcase them as a vendor!

Generating sequences

Messages
2
Hello,
My question is perhaps very specific. I want to create a very specific timing of DMX values, based upon an existing timeline that creates a video that the DMX effects will be synchronised with. So I would like to know how I can write a (text?) file that might be built of lines like:
timestamp dmx_channel dmx_value

I created a similar output for the midi files for sound generation for the video, based upon the standard for MIDI files. It was semi-horrible (MIDI files are binary, there are lots of strange compression things because files in the 1980s were smaller, etc) but doable. Is there a similar file format I can use for xLights?

The resulting DMX file would then be played in parallel with the video files using multiple FPP modules synchronising for the complete experience.

Any ideas?

Thank you,
Tim
 
Messages
2
In reply to my question, in case anyone ever tries to do it.
YES! This is possible.
Some notes:
A frame is 512 DMX values. (or perhaps a multiple of this - I did 512 values because I only needed 2)
You decide how often a frame is sent. So e.g. 40 milliseconds in 25 frames per second.
The digital file has some parameters in the header block (60 bytes), then lots of 512 byte frames.
Version 1 files are simpler and have no compression.
Multibyte values are little-endian.
Official description is here:
Third party description is here:

The program I wrote (in Processing) output data as hex values to a file called dmxout.dig. First a 60 byte header, then blocks of 512 values as a frame.
This were converted to binary values using the command:

xxd -r -p dmxout.dig dmxout.fseq

Then use a binary file editor (I use FilePeek on OSX) to replace aa aa aa aa with the number of frames in little endian format, I.e. (length-60) / 512. If you knew in advance how many frames you were going to have, you could insert that straight into the header.

Processing code for this is below. This code is not self contained, but this was just one part of a sprawling script. I hope the variable names are all useful and clear enough.

Please get in touch with questions if you are trying to use this and having no luck. It worked, and it is not very complicated.


JavaScript:
void setupDMXout(){
  // set up DMX file output
  DMXfileOutput = createWriter("dmxout.dig");
  lastDMXframeTime = 0;
 
  // now create the header
  // 28 bytes
  byteOutDMX('P');  //bytes 0-3
  byteOutDMX('S');
  byteOutDMX('E');
  byteOutDMX('Q');
  byteOutDMX(60); // offset to data start
  byteOutDMX(0);
  byteOutDMX(0);  // minor version number
  byteOutDMX(1);  // major version number
  byteOutDMX(28); // offset to variable header low byte
  byteOutDMX(0);  // high byte
  byteOutDMX(0);  // channels per frame, 4 bytes, 0x00000200 = 512  //bytes 10-13
  byteOutDMX(2);
  byteOutDMX(0);
  byteOutDMX(0);
  byteOutDMX(0xaa); // number of frames. this needs to be inserted at the end
  byteOutDMX(0xaa);
  byteOutDMX(0xaa);
  byteOutDMX(0xaa);
  byteOutDMX(40);  // step time in milliseconds, 40 = 25fps
  byteOutDMX(0);  // reserved
  byteOutDMX(0); // universe count, ignored by fpp / xlights //bytes 20-21
  byteOutDMX(0);
  byteOutDMX(0); // universe size, ignored by fpp / xlights
  byteOutDMX(0);
  byteOutDMX(1);  //gamma, should be 1, ignored by FPP
  byteOutDMX(2);  // colour encoding, 2 for RGB, ignored by FPP
  byteOutDMX(0); // reserved - should be zero
  byteOutDMX(0); // reserved - should be zero  //bytes 26-27
  // start variable header
  byteOutDMX(32);  //  the length of the variable header, 2 bytes
  byteOutDMX(0);
  byteOutDMX('s');  // sp = sequence producer
  byteOutDMX('p');
  byteOutDMX('T');
  byteOutDMX('i');
  byteOutDMX('m');
  byteOutDMX('e');
  byteOutDMX('s');
  byteOutDMX(' ');
  byteOutDMX('U');
  byteOutDMX('p');
  byteOutDMX(' ');
  byteOutDMX('H');
  byteOutDMX('y');
  byteOutDMX('d');
  byteOutDMX('r');
  byteOutDMX('o');
  byteOutDMX('p');
  byteOutDMX('i');
  byteOutDMX('a');
  byteOutDMX(' ');
  byteOutDMX('2');
  byteOutDMX('0');
  byteOutDMX('2');
  byteOutDMX('5');
  byteOutDMX('-');
  byteOutDMX('2');
  byteOutDMX('0');
  byteOutDMX('4');
  byteOutDMX('7');
  byteOutDMX(0);  // NULL terminated string
  // the next byte should be byte 60, which is the offset in byte 4 above
  // data frames start here, blocks of 512 bytes
}
int byteOutDMXCount=0;
void byteOutDMX (int byteOut){
  DMXfileOutput.print(hex(byteOut,2)+" ");
  byteOutDMXCount++;
  if (byteOutDMXCount >31){
    DMXfileOutput.println(" ");
    byteOutDMXCount=0;
  }   
  // try flushing at every byte to make sure all data is saved  20251009
  // was every line, but that leaves some undone
  DMXfileOutput.flush();  // Writes the remaining data to the file
}

void zeroesOutDMX(int numZeroes){
  for (int i =0; i< numZeroes; i++) {
      byteOutDMX(0);
  }
}


// for just two values
void DMXframeOut2(int v1, int v2){
  while (lastDMXframeTime < (nowtime-4)){
    // output 512 zeros
    zeroesOutDMX(512);
    lastDMXframeTime +=4;
  }
  // print channels
  byteOutDMX(v1);
  byteOutDMX(v2);
  zeroesOutDMX(512 - 2);
  // this is the last frame
  lastDMXframeTime +=4;
}
 
Top Bottom