Coder Social home page Coder Social logo

x42 / libltc Goto Github PK

View Code? Open in Web Editor NEW
198.0 34.0 55.0 723 KB

Linear/Logitudinal Time Code (LTC) Library

Home Page: http://x42.github.io/libltc/

License: GNU Lesser General Public License v3.0

Shell 3.09% C 92.32% Makefile 2.06% M4 2.54%
smpte ltc timecode

libltc's Introduction

libLTC

Linear (or Longitudinal) Timecode (LTC) is an encoding of SMPTE timecode data as a Manchester-Biphase encoded audio signal. The audio signal is commonly recorded on a VTR track or other storage media.

libltc provides functionality to encode and decode LTC audio from/to SMPTE or EBU timecode, including SMPTE date support.

libltc is the successor of libltcsmpte. For more information, please see the FAQ in the documentation.

Documentation

The API reference, examples, as well as introduction can be found at

https://x42.github.io/libltc/

This site is part or the source-code in the doc/ folder.

libltc's People

Contributors

huetremy avatar kaidoe avatar luigi avatar martindelille avatar nphilipp avatar x42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libltc's Issues

Tweak user-bit math

Remaining part from #51 -- needs platform tests and check (ARM in particular)

diff --git a/src/ltc.c b/src/ltc.c
index bc54353..03afb1d 100644
--- a/src/ltc.c
+++ b/src/ltc.c
@@ -312,21 +312,21 @@ void ltc_encoder_set_user_bits(LTCEncoder *e, unsigned long data){

 unsigned long ltc_frame_get_user_bits(LTCFrame *f){
  unsigned long data = 0;
- data |= f->user8;
+ data += f->user8;
  data <<= 4;
- data |= f->user7;
+ data += f->user7;
  data <<= 4;
- data |= f->user6;
+ data += f->user6;
  data <<= 4;
- data |= f->user5;
+ data += f->user5;
  data <<= 4;
- data |= f->user4;
+ data += f->user4;
  data <<= 4;
- data |= f->user3;
+ data += f->user3;
  data <<= 4;
- data |= f->user2;
+ data += f->user2;
  data <<= 4;
- data |= f->user1;
+ data += f->user1;
  return data;
 }

Avoid buffer copy with ltc_decoder_write_ template

Hi,

Just as an improvement, I see that the template function ltc_decoder_write_ is reallocating a buffer sized of LTC_CONVERSION_BUF_SIZE on the stack at every call.

It would be interesting to change the decode_ltc parameters instead and add the format of the passed sample, or update the ltc_decoder_create function to support the type of samples?

BR

Read LTC from one channel of a mult-channel wav

Hello

I'm trying to decode the LTC from a single channel of a multi-channel wav. I can read in a mono version of the file in question without a problem, however the stereo version gives me nothing.

I've kept the file in 8 bit 44.1khz, and if I make a stereo wav with (the same) LTC on both channels then the file reads. Is there any solution?

Thanks!

Richard

Packed (interlaced) audio data

Hi,

Currently using Portaudio for retrieving audio signal, I saw that ltc decoder does not support interlaced data (for 16bits for instance). I had to create my own template.

I have made a working prototype for s16i template. Any chance to see this update upstream?

16 bit to 8 bit Conversion not yielding any results

I converted the output.raw file from the tests folder to an mp3. In my code I'm playing back the mp3 and getting back linear PCM 16 bit samples. I'm using the following conversion to take the Sint16 to ltcsnd_sample_t.

       SInt16 *samples ...
       ltcsnd_sample_t convertedSamples[BUFFER_SIZE] ...
       /* Omitted Code for brevity */ 
       for (int i=0; i < n; i++) {
            SInt8 tempSigned8Bit = samples[i+total] / 256;
            convertedSamples[i] = tempSigned8Bit + 128;
        }

Is this conversion the right way to go?

Decoder not parsing the direct output of the Encoder

Clearly I'm doing something dumb here. This is intended to be a very simple test of LTC encoding on macOS (arm64) - the code below is in Swift, calling directly to libltc through Swift's support for C interop.

Our intention is to generate (and playback) single LTC frames from our app when an event occurs, for timesync to that specific event from external cameras.

The code below generates a single LTC-encoded audio frame for the current time at a given fps/sample-rate, and then (as a sanity check) tries to decode that same frame (as stored in buffer). But the decode fails to parse an LTC, returning 0 from ltc_decoder_read. The actual values that the Encoder is writing into buffer for each sample are attached, and I've verified that Decoder does in fact read them appropriately when indexing into buffer in C-land. They seem at least superficially correct, as they're in the 38-218 range.

EncoderSamples-44100Hz-30fps.txt

// MARK: - LTC Input

let date = Date()
var calendar = Calendar.current
calendar.timeZone = .init(abbreviation: "UTC")!

let seconds = calendar.component(.second, from: date)
let minutes = calendar.component(.minute, from: date)
let hour = calendar.component(.hour, from: date)

let day = calendar.component(.day, from: date)
let month = calendar.component(.month, from: date)
let year = calendar.component(.year, from: date) % 2000

var timecode = SMPTETimecode()
let timezone = "+0000".utf8CString
timecode.timezone = (timezone[0], timezone[1], timezone[2], timezone[3], timezone[4], timezone[5])
timecode.days = UInt8(day)
timecode.hours = UInt8(hour)
timecode.mins = UInt8(minutes)
timecode.secs = UInt8(seconds)
timecode.months = UInt8(month)
timecode.years = UInt8(year)
timecode.frame = 0

// Along with the sample rate, determines the duration of individually encoded frame (i.e. timecode).
let fps: Double = 30

let encoder = ltc_encoder_create(Double(sampleRate), fps, LTC_TV_525_60, Int32(LTC_USE_DATE.rawValue))
ltc_encoder_set_timecode(encoder, &timecode)

// We need to write two frames to properly encode a single frame - size the buffer accordingly.
var encodedSize = ltc_encoder_get_buffersize(encoder)
var buffer: [ltcsnd_sample_t] = Array(repeating: 0, count: 2 * encodedSize)

ltc_encoder_encode_frame(encoder)
let primaryFrameOffset = ltc_encoder_copy_buffer(encoder, &buffer)
ltc_encoder_end_encode(encoder)
// The call to end_encode writes an additional frame and clears the internal buffer - we need to copy that back over.
ltc_encoder_copy_buffer(encoder, &buffer[Int(primaryFrameOffset)])

for i in 0..<encodedSize {
    print("Sample \(i): \(buffer[i])")
}

// MARK: - Verify Encoding

let decoder = ltc_decoder_create(Int32(Double(sampleRate) / fps), 2)
ltc_decoder_write(decoder, &buffer, encodedSize, 0)

var decodedFrame = LTCFrameExt()
let res = ltc_decoder_read(decoder, &decodedFrame)
print("Decoded Frame: ", res)

var decodedTimecode = SMPTETimecode()
ltc_frame_to_time(&decodedTimecode, &(decodedFrame.ltc), 0)

print("Wrote:  \(timecode)")
print("Decoded: \(decodedTimecode)")

exit(0)

Initial start offset problem

With current version (2013-07-26), I get

position=     -20     1599,    period=20
position=    1600     3199,    period=20
position=    3200     4799,    period=20
position=    4800     6399,    period=20
....

If I make a change to decoder.c

                if (d->frame_start_prev < 0) {
                        /* d->frame_start_off = posinfo - d->snd_to_biphase_period; */
                        d->frame_start_off = posinfo;
                } else {
                        d->frame_start_off = d->frame_start_prev;
                }

I get

position=       0     1599,    period=20
position=    1600     3199,    period=20
position=    3200     4799,    period=20
position=    4800     6399,    period=20
...

as expected.

I have no idea if this is a good idea.

Renaming a couple of functions

I think it would be beneficial to rename
ltc_encoder_get_buffer
to
ltc_encoder_copy_buffer
since that's what the function is actually doing.

In many APIs I have worked verbs such as 'copy' or 'create' are associated with memory allocations so the user is responsible for releasing the resources allocated. Whereas 'get' is just for retrieving a value or a pointer to something. I personally think it's a pretty good convention to follow. For example in your API ltc_encoder_get_bufptr would already follow this idea.

We could temporarily do something like:
#define ltc_encoder_get_buffer ltc_encoder_copy_buffer
to avoid breaking code that is using the former name.

Also for consistency with etc_encoder_get_buffersize:
etc_encoder_set_bufsize should be renamed to etc_encoder_set_buffersize

Let me know what you think.

CMake support?

Dear Robin,

Your library is working like a charm under Windows, but there is no quick way for Windows users to build the library (even with few .c, .h file). CMake is more and more used nowadays and thus not easy to learn, it offers good crossplateform solution avoiding the use of plateform specific scripting mechanic.

I started to create a CmakeLists.txt some time ago (https://github.com/lp35/libltc/blob/master/CMakeLists.txt), and thus it requires some update for package config generation & debian packaging, I would love to see it upstream.

Do you have any objection about moving to CMake?

ltc_decoder_write_u16

HI , I bought the ANSI C book and built audio IO for Arduino Due with I2S :)
I am succesfully bringing in 32 bit samples from codec over I2S into Arduino Due with Passthough back out to Codec. The Due has a lot more power going for it than the arduino Uno so I don't have the inturupt issue now.

code here

https://github.com/benbiles/TimeCode-Shield/blob/master/timecodeshield

I am copying the samples to unsigned short int for ltc_decoder_write_u16 wrapper with

samples = ((rdat >> 16) & 0xffff); // copy rdat , unsigned long int to unsigned short int

then

ltc_decoder_write_u16 (decoder, &samples,1, 0); // write unsigned short to ltc_decoder_write_u16 ready to be processed by libltc.

I am getting nothing from this in the void loop()

LTCFrameExt frame;
while (ltc_decoder_read (decoder, &frame) > 0) {
SMPTETimecode stime;
ltc_frame_to_time(&stime, &frame.ltc, 1);
Serial.print("working?");
Serial.print(stime.hours);
Serial.print(stime.mins);
Serial.print(stime.secs);
Serial.print(stime.frame);

this returns nothing..
Serial.print(ltc_decoder_read (decoder, &frame));

Serial.print(samples); brings a list of 16bit numbers that appear to be of maximum 65535 (unsigned short int)

Interestingly the numbers decrease in size when I maximise audio input volume and increase when I reduce volume. This is perhaps normal?

I tried converting samples back to 32bit with
junk = ((samples << 16) & 0xffff);
and sending junk back out of the codec and the timecode sounds normal.

I think I2S sends standard PCM samples so it should be compatible with LIBLTC.

Is there another variable I could print or test to see if ltc_decoder_write_u16 (decoder, &samples,1, 0); is actually sending the LTC library anything at all ?

I tried sending 8bit unsigned char also but no timecode returns from libltc as of yet.

Any ideas would be greatly appreciated :)

filtering introduces small DC offset

I have noticed that for every value except rise_time = 0, the filtering process introduces a small DC offset in the LTC square wave making the wave no longer being centered around zero. I haven't delved into it to understand why it happens and in my system this doesn't affect the readability of the encoded signal so everything still works. However I was wondering if it's something that is possible to fix.

Trouble with building

Hi, I wanted to build libltc on OS X 10.8.

To get a configure file, I used autoconf (v 2.69 from Homebrew) but this returned:

$ autoconf
configure.ac:26: error: possibly undefined macro: AM_INIT_AUTOMAKE
If this token and others are legitimate, please use m4_pattern_allow.
See the Autoconf documentation.
configure.ac:27: error: possibly undefined macro: AM_CONFIG_HEADER
configure.ac:35: error: possibly undefined macro: AC_PROG_LIBTOOL
configure.ac:36: error: possibly undefined macro: AM_PROG_LIBTOOL
configure.ac:37: error: possibly undefined macro: AM_PROG_CC_C_O
configure.ac:38: error: possibly undefined macro: AC_LIBTOOL_WIN32_DLL

After that, running ./configure simply returned the following:

$ ./configure
checking for sed... /usr/bin/sed
checking libltc version... 1.1.1
configure: error: cannot find install-sh, install.sh, or shtool in "." "./.." "./../.."

I do have shtool in /usr/local/bin/shtool .

I'm kind of new to building projects on Mac. Does the configure.ac need some modification?

Thanks,

Mattias

29.97fps drop/non-drop frame

Hi,
i got a problem decoding audio files at 29.97fps dropping and non-drop frame.
It is like at 29.97fps ndf i am losing a 1second every 30mins, and at 29.97 i am gaining a 1 second every 30mins.
I have been looking at ltc_frame_to_time() but i do not see where i can find a solution.
Do you have any advice?
Cheers,
S.

support for decoding 64bit floating-point buffers

Hi Robin,

thanks for writing such a simple and clean API.
Your library is working really well for my purposes.

In the app I am working on at the moment I am dealing with Core Audio and 64-bit floating point audio buffers. I see that in your library there is only a wrapper function for decoding 32-bit floats.

void ltc_decoder_write_float(LTCDecoder *d, float *buf, size_t size, ltc_off_t posinfo);

I would like to add a wrapper for doubles as well.

If you agree to it, I can send you a PR.
Thanks for your consideration.

Decoder - "d->biphase_tics[d->biphase_tic]" assembled incorrectly

The function 'biphase_decode2()' is called twice for each bit in the LTC frame.
https://github.com/x42/libltc/blob/master/src/decoder.c#L307

Since 'biphase_tic' is increased each time, it overflows (is limited by '% LTC_FRAME_BIT_COUNT') and the array is first filled with the early bits and then overwritten with later bits in the frame.
https://github.com/x42/libltc/blob/master/src/decoder.c#L264

	d->biphase_tics[d->biphase_tic] = d->snd_to_biphase_period;
	d->biphase_tic = (d->biphase_tic + 1) % LTC_FRAME_BIT_COUNT;

Either the array should only be filled on the 2nd calling/phase of the bitstream, or the array should be bigger to hold all 1/2 phases.

Help with understanding how to approach realtime en-/decode...

Hi,

like so many other people that posted here, i'd like to make an attempt to realtime encode / decode. I am very unexperienced with programming and electronics so this project has a huge learning curve for me. Platform will be a Teensy 3.2 and i think the onboard ADC / DAC are sufficient for the timecode signal purposes. I am in the process of figuring a way to condition the signal electrically to use the full ADC range but in parallel i am starting some experiments reading audio from the ADC.

With my rudimentary programming knowledge i tried to read trough the code and examples of libltc but there are some things i couldnt really get. For example:

  • What is the minimum sample number that libltc needs to be fed to read a timecode? (i guess it depends on the FPS and Samplerate as well, so lets assume 25fps @ 44.1khz). Wouldnt be as easy as 44100/25, or is it, 1764 samples? If so, the longest buffer that would be required to read timecode would be that for [email protected], so 1840 samples (rounded)?

  • Timing question: I have a #DS3231 TXCO module connected to the Teensy, the ultimate goal is to "discipline" this from a GPS signal for TC Generation or to sync it to the incoming Timecode Signal for freerun operation. If i can have a time source more precise than seconds (i.e. the DS3231 has a 32khz and a frequency configurable squarewave output, i.e. 1024hz) ... can i libltc make use of that - or would it not be of any advantage anyways?

  • Clipping: Given the amount of output signals that one might encounter for TC Input (headphone level, -10db level, +4db level) i wonder how complicated the condition circuit needs to be. i was considering to use some auto gain to raise everything to 5v peak-to-peak (also to have a common voltage bias i can predict and move) and then bring it down to reasonable ADC levels. But i am just wondering: given the nature of the SMPTE signal, i guess that timecode signal is pretty solid even when clipping, right?

Cheers,
T.

Zoom F6 Timecode not working?

I have tried running the ltcdump on a file that was recorded on a Canon EOS R with the timecode coming from the Zoom F6 timecode port into the mic port of the EOS R.

For some reason, it seems to not recognize this time code at all?

Am I doing something wrong here? The strange thing is that the Tentacle Sync Studio successfully reads the timecode with no problem?

I also am discussing this with the ltcsync dev at arikrupnik/ltcsync#28

There I also provided a small demo file CSP_8307-1-right.wav.zip

I hope we can figure this out and get it to work.

Thank you.

More of a question: Examples

Hi,

This isn't really an issue but I was looking for an example that stores the LTC to the audio track of a video file or something like that. Have anything handy?

Thanks,
Brad

LTCWRITE_TEMPLATE functions broken

These do not work for buffers over 1024 samples, because they copy the first bytes in the input buffer repeatedly into the ltc write buffer. Here is suggested code for ltc.c:

#define CONVERSION_BUF_SIZE 1024

#define LTCWRITE_TEMPLATE(FN, FORMAT, CONV) \
void ltc_decoder_write_ ## FN (LTCDecoder *d, FORMAT *buf, size_t size, ltc_off_t posinfo) { \
        ltcsnd_sample_t tmp[CONVERSION_BUF_SIZE]; \
        size_t copyStart = 0; \
        while (copyStart < size) { \
                int c = size - copyStart; \
                c = (c > CONVERSION_BUF_SIZE) ? CONVERSION_BUF_SIZE : c; \
                int i; \
                for (i=0; i<c; i++) { \
                        tmp[i] = CONV; \
                } \
                decode_ltc(d, tmp, c, posinfo + (ltc_off_t)c); \
                copyStart += c; \
        } \
}

LTCWRITE_TEMPLATE(float, float, 128 + (buf[copyStart+i] * 127.0))
/* this relies on the compiler to use an arithemtic right-shift for signed values */
LTCWRITE_TEMPLATE(s16, short, 128 + (buf[copyStart+i] >> 8))
/* this relies on the compiler to use a logical right-shift for unsigned values */
LTCWRITE_TEMPLATE(u16, unsigned short, (buf[copyStart+i] >> 8))

Install script

could you please provide a bash install script fo Raspberry Pi (Stretch & Buster) which installs all and everything, starting with download, then extract zip or tar archive, then create all directories and links and paths and everything which is required?

Unable to link to libltc.so.11

I downloaded the libltc-1.3.0.tar.gz, ran ./configure, make, sudo make install and then ran gcc against the ltcencode example:

gcc ./ltcencode.c -lltc -o ltcencode

I get the following error:.
/ltcencode: error while loading shared libraries: libltc.so.11: cannot open shared object file: No such file or directory

I used ldd to see the .so being used. It says libltc.so.11. There are two libltc.so files that are installed. One in /usr/local and one in /usr/local/lib.

When I run ls -la on any of the shared libraries, I get the following info
/usr/local/libltc.so.11 -> /usr/local/lib/libltc.so
/usr/local/lib/libltc.so -> libltc.so.11.0.5
/usr/local/lib/libltc.so.11 -> libltc.so.11.0.5

I assume that either reference to libltc.so.11 resolves to libltc.so.11.0.5.

Any recommendations to get the link working?

Timecode not detected if audio stream doesn't initially contain valid timecode

I've noticed that if I start decoding from an audio stream that doesn't initially contain any timecode data, but after a short period of time if I un-mute the timecode audio, the decoder doesn't always start to return any decoded timecode.

If I then destroy the decoder and create it again using ltc_decoder_free() and ltc_decoder_create() and feed it with audio samples that contain valid timecode data right from the start, then it always returns the decoded timecode.

Any ideas or suggestions that I could try to make the library reliably detect timecode when the audio stream doesn't initially contain any timecode?

ltcencode and ltcdecode unexpected results

Hi,
I've just installed libltc and run into an issue that I'm not sure is the correct behaviour:

# ./ltcencode test
sample rate: 48000.00
frames/sec: 25.00
secs to write: 2.00
sample format: 8bit unsigned mono
Done: wrote 96000 samples to 'test'
# ./ltcdecode test
* reading from: test

Should the results of ltcencode be readable by ltcdecode? I'd expect so. I've also tried playing with the decode sample rate but receive the same results.

I've been getting funny results with ltcdecode from other audio sources (MOTU micro express, android LTC generator), but thought I'd check the simplest case with you first.
Server is running CentOS 6.6 2.6.32-431.el6.x86_64

realtime audio IO

Hi, I'm looking for a way to write / read audio frames ( data ) to / from a libltc buffer for decoding encoding LTC audio.

I found this line of code in the tests folder
n = fread(sound, sizeof(ltcsnd_sample_t), BUFFER_SIZE, f);

am I right in thinking this line is reading in frames of audio from the file ?

I'd like to read / write to from DAC/ADC wired up to an arduino using libltc.

I could bring in samples from I2S on an arduino duo with the I2S library but I'm also thinking
the Manchester encoded LTC would probably survive 8bit 16khz audio over PWM on a arduino uno.

before I try and code this I just wondered if there is something in the library that already supports reading / writing to from audio codec hardware ? or the library is mainly setup for jack and ALSA in lunux ?

sorry for my simple questions here. I'm not the best C programmer and don't want to reinvent the wheel if the library is already doing what I want ?

thank, ben

Using a live input stream?

Hi, thank you again for your code. I have it working great with the testfile, but am a bit stuck on how to use a live input stream. I have one of these:

http://www.pinknoise-systems.co.uk/tentacle-single-set.html

Which plugs into the mic port of the computer (Windows 10) and streams in LTC data.

Is anyone using live input with this library? If you could point me at an example, or some tips, it would be much appreciated. Thanks!

fyi: java wrapper

@x42 not sure if you got my email; just fyi I've made a java wrapper for this, and am using said wrapper in a commercial, closed source project.

Pretty sure that complies with the LGPL license but I wanted to do due diligence before releasing it commercially.

https://github.com/BernsteinA/libltc-jni

getting the LTC volume

I would like to add support for getting the LTC volume in dBFS:
double ltc_encoder_get_volume(LTCEncoder *e)

reading live data in windows?

Hi, thank you for your lib, I have it compiled in visual studio, and the test with a file works great. Now though, I need to get a live input stream working. Is there a windows-friendly version of this around? I am looking at ltc-tools/ltcdump.c, but it seems linux only.

Thanks again.

Not detecting LTC audio sync

I'm trying to extract the timecode from my LTC signal created by LTC Timecode Generator (Android) and recorded to 3 different camera's, but the timecode isn't recognized by ltcdump and not consistently recognized by tentacle sync.

This is what the waveform looks like.
schermafbeelding 2017-11-01 om 09 39 07

How can I improve the consistency of the LTC, and recognizeblility.

Using libtlc with NDK in an Android App: unsigned char and ltcsnd_sample_t representation

hey guys,

I'm trying to use libltc in an android app (for wireless ltc-distribution). Do you have any experiences about that?

First thing I stumbled over is that the NDK seems to interpret the unsigned chars of SMPTETimecode-Object in a strange way. If I assign the time like in the libtlc-example:

my_timecode.years =18; my_timecode.months =3; my_timecode.days =18;

the debugger tells me that
years = {unsigned char} '\x12' months = {unsigned char} '\x03' days = {unsigned char} '\x12'

So I changed the assignment to
my_timecode.years ='18'; my_timecode.months ='3'; my_timecode.days ='18';

Second thing, and I'm not sure if this is the consequence of the issue above, is that the encoded timecode looks like that:

"������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������+&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������+&&&&&&&&&&+������������+&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������+&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������+&&&&&&&&&&+������������������������+&&&&&&&&&&+������������+&&&&&&&&&&&&&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������������������+&&&&&&&&&&+������������+&&&&&&&&&&+������������+&&&&&&&&&&&&&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������+&&&&&&&&&&+������������������������+&&&&&&&&&&+������������+&&&&&&&&&&&&&&&&&&&&&&+������������+&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������+&&&&&&&&&&+������������������������+&&&&&&&&&&+������������+&&&&&&&&&&+������������+&&&&&&&&&&&&&&&&&&&&&&+������������������������+&&&&&&&&&&&&&&&&&&&&&&+������������+&&&"...

which isn't a legal timecode, right? Or is this a way of representing data of the ltcsnd_sample_t-object?

Looking forward to hear from you!
Greetings from cologne/germany.

image

What kind of Audio should I use with decode

Hi there, I have followed the docs and tried to use a wav file with the decode function but it is not working. I am not sure what format should I use: aiff, wav? what encoding settings?

What I mean is: I am using unsigned 8-bit and it is not working.

Compiling under Windows + real time decoding

Hello!
First of all, thank you very much for this code and all the resources provided with it.
It has been of great help to better understand how to decode LTC from an audio source.

My goal is to integrate this library into a previously written code (on windows) that reads in real time audio data from a soundcard (using ASIO callbacks) and then decodes it.

I compiled libltc under linux (on cloud9, using make and make check) and everything went as expected: the make check was successful and the timecode.raw file was flawlessly decoded.

Unfortunately, while compiling it in Visual Studio and I encountered few problems, but I quickly fixed them:

  1. rint() identifier not found (fixed by manually force the code inside the #if macro)
  2. return -infinity; "infinity" undeclared identifier. I fixed it by adding the line:
    double infinity = std::numeric_limits<double>::max()

However, once I run the ltcdecode.cpp with the following parameters (timecode.raw 882) as done in the make check, I get the following output on terminal:

* reading from: timecode.raw
2000-00-00 +0000 00:05:27:17 | 626 1511

(that it's coherent with the first two lines of the linux output), but then it returns without decoding the rest.

Do you have any suggestion? Why is it not properly decoding the whole file?

Thank you in advance!

Using winmm.lib to decode real time LTC input?

Hi, and thank you very much for this code. I am streaming in LTC from a master clock, and am attempting to pick it up using winmm.lib, which streams the signal into a:

short int waveIn[44100 * 3];

Am i correct in thinking that libltc decoding needs an unsigned char* ?

Can I use something similar to the below code, or do i need a queue of some kind for real time streaming?

The signal is checked and is valid ltc.

Thanks!

void Start()
{
	const int NUMPTS = 44100 * 3;   // 3 seconds
	int sampleRate = 44100;

	HWAVEIN      hWaveIn;
	MMRESULT result;

	WAVEFORMATEX pFormat;
	pFormat.wFormatTag = WAVE_FORMAT_PCM;     // simple, uncompressed format
	pFormat.nChannels = 1;                    //  1=mono, 2=stereo
	pFormat.nSamplesPerSec = sampleRate;      // 44100
	pFormat.nAvgBytesPerSec = sampleRate * 2;   // = nSamplesPerSec * n.Channels *    wBitsPerSample/8
	pFormat.nBlockAlign = 2;                  // = n.Channels * wBitsPerSample/8
	pFormat.wBitsPerSample = 16;              //  16 for high quality, 8 for telephone-grade
	pFormat.cbSize = 0;

	// Specify recording parameters
	result = waveInOpen(&hWaveIn, WAVE_MAPPER, &pFormat,
		0L, 0L, WAVE_FORMAT_DIRECT);

	WAVEHDR      WaveInHdr;
	WaveInHdr.lpData = (LPSTR)waveIn;
	WaveInHdr.dwBufferLength = NUMPTS * 2;
	WaveInHdr.dwBytesRecorded = 0;
	WaveInHdr.dwUser = 0L;
	WaveInHdr.dwFlags = 0L;
	WaveInHdr.dwLoops = 0L;
	waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));

	// Insert a wave input buffer
	result = waveInAddBuffer(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));

	// decode stuff
	int apv = 1920;
	ltcsnd_sample_t sound[BUFFER_SIZE];
	size_t n =0;
	long int total =0;
	LTCDecoder *decoder;
	LTCFrameExt frame;
	decoder = ltc_decoder_create(apv, 32);

	// Commence sampling input
	result = waveInStart(hWaveIn);

	int num = 0;
	while (num < 200)
	{
		cout << "recording..." << endl;

		sound[0] = waveIn[0]; // this is wrong. Do I need to convert to unsigned char?

		ltc_decoder_write(decoder, sound, n, total); // do i need to write before i read?
		
                ltc_decoder_read(decoder, &frame);
		SMPTETimecode stime;
		ltc_frame_to_time(&stime, &frame.ltc, 1);

		std::cout << stime.frame << std::endl;		  // prints a strange character	
		
		num += 1;
	}
	
	waveInClose(hWaveIn);
	ltc_decoder_free(decoder);
	PlayRecord();
}

Looking to optimize precision of 'frame.off_start'

I have been working with the sister project LTC-tools to feed an externally generated LTC signal into NPT/Chrony, with pretty good success.... Here's some 30NDF analysed by Chrony
better3

What is clear in the image is the horizontal banding, with the bands being ~20us apart (this is the 48KHz sample rate). It would seem that perhaps the integer nature of 'frame.off_start' is causing some jitter in the reported timing. Even though the timing is precise enough to record the variance, I am getting a swing of ~10 samples in detected 'off_start'.

I have looked at 'decoder.c' and it's not really clear to me how it 'finds' the start of the frame.

Dumping the biphase info I get:

00-00-00 +0000 03:22:31:13
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 20.000000, 
:267, 842, 1600.000000

00-00-00 +0000 03:22:31:14
19.999060, 19.999060, 19.999296, 20.499472, 19.874603, 19.874603, 19.905952, 19.905952, 
19.929464, 19.929464, 19.947098, 19.947098, 19.960323, 19.960323, 19.970243, 19.970243, 
19.977682, 20.483261, 19.862446, 19.896835, 19.922626, 19.922626, 19.941969, 19.941969, 
19.956476, 19.956476, 19.967358, 19.967358, 19.975519, 19.975519, 19.981638, 19.981638, 
19.986229, 19.986229, 19.989672, 19.989672, 19.992254, 19.992254, 19.994190, 19.994190, 
19.995644, 19.995644, 19.996733, 19.996733, 19.997549, 19.997549, 19.998161, 19.998161, 
19.998621, 19.998621, 19.998966, 19.998966, 19.999224, 19.999418, 19.999563, 19.999672, 
19.999754, 20.499817, 19.874863, 19.906147, 19.929609, 19.947206, 19.960405, 19.970304, 
19.977728, 20.483295, 19.862473, 19.896854, 19.922640, 19.941980, 19.956486, 20.467363, 
19.850523, 19.887892, 19.915918, 19.936939, 19.952705, 19.952705, 19.964529, 20.473396, 
:843, 392, 1599.809204

The last line is 'off_start', 'off_end' and the sum of the biphase bit timing. Typically I see all '20.0000', some frames show different values.

Does anyone have suggestions on how this might be improved (less variance), or where to look at the code?

NodeJS version

Hi all,

Has anyone used this library with javascript? I'm trying to get this into a NodeJS project but not sure if it'd be best to rewrite or bridge into js. Thoughts?

integer overflow in decode_ltc

In decoder.c, decode_ltc method, lines 309, 310, 317; the int offset parameter of biphase_decode2 can overflow if i > INT32_MAX.

Changing offset to an int would require changing the public API, so that's probably a no go. Is it ok to early out if i > INT32_MAX?

encode a full LTC frame in reverse

Hi Robin,
I would also like to include a convenience function for that.

void ltc_encoder_encode_frame_reversed(LTCEncoder *e);

Trivial to add and I think it would make for a more symmetric API.
If you agree I can send you a PR. Thanks.

decode example fails on an ltc wav file

Hi, thank you for this code. i am trying to get the example decode to run, and it does not seem to read my file. The file data is valid. The code is:


int main(int argc, char **argv) {
	int apv = 1920;
	ltcsnd_sample_t sound[BUFFER_SIZE];
	size_t n;
	long int total;
	FILE* f;
	char* filename;

	LTCDecoder *decoder;
	LTCFrameExt frame;

	f = fopen("LTC_00_00_00_00__1mins_24.wav", "r");

	if (!f) {
		fprintf(stderr, "error opening '%s'\n", filename);
		return -1;
	}
	fprintf(stderr, "* reading from: %s\n", filename);

	total = 0;

	decoder = ltc_decoder_create(apv, 32);

	do {
		n = fread(sound, sizeof(ltcsnd_sample_t), BUFFER_SIZE, f);
		ltc_decoder_write(decoder, sound, n, total);
               //    gets to here
	
		while (ltc_decoder_read(decoder, &frame)) { // Never gets past here
			SMPTETimecode stime;

What could be happening here? Should a .wav work with this example? Thanks!

const correctness

Would you be interested in making libltc const-correct?
I think it's a pretty simple API so it shouldn't be too difficult to do.
I think about a dozen of functions would be affected.

I may have a PR ready for this.
Let me know...

libltc decoder returning zero

I'm reading in realtime LTC from a timecode generator in through PortAudio in order to record it. Then I pass samples to the decoder:

////
data.decoder = ltc_decoder_create(data.apv, 1024);
////

in the callback function:

ltc_decoder_write_float(data->decoder, &data->recordedSamples[6][0], framesToCalc, data->frameIndex);

printf("queue %d",ltc_decoder_queue_length(data->decoder));

while (ltc_decoder_read(data->decoder, &data->frame)) {
	SMPTETimecode stime;

	ltc_frame_to_time(&stime, &data->frame.ltc, 1);

... etc etc

i've tried changing the window size, apv, queue size, etc, all returning zero. it seems that the maximum and minimum are being read, however.

Subtle bug in ltc_encoder_set_filter()

ltc_encoder_set_filter() sets the filter_const field to zero in case rise_time is <= zero.
e->filter_const should be set to 1.0 instead. That's the correct value for the filter constant when no filtering has to take place. Terms will cancel out and your filter equation will return exactly the original sample.
However you are conditionally running your filter loop based on the (wrong) value of the filter constant, so we need to change the condition inside the addvalues() function as well.
if (tcf > 0) should become if (tcf < 1.0)

I realized about this because ltc_encoder_get_filter() kept returning the wrong value for rise_time = 0.

iOS audio jack example code

Sample code how to use the lib within an iOS app (getting the timecode from the audio jack) would be nice.

16 bit to 8 bit Conversion not yielding any results

I converted the output.raw file from the tests folder to an mp3. In my code I'm playing back the mp3 and getting back linear PCM 16 bit samples. I'm using the following conversion to take the Sint16 to ltcsnd_sample_t.

       SInt16 *samples ...
       ltcsnd_sample_t convertedSamples[BUFFER_SIZE] ...
       /* Omitted Code for brevity */ 
       for (int i=0; i < n; i++) {
            SInt8 tempSigned8Bit = samples[i+total] / 256;
            convertedSamples[i] = tempSigned8Bit + 128;
        }

Is this conversion the right way to go?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.