{"id":19412692,"url":"https://github.com/cppplayground/ltc-lineartimecode-smpte","last_synced_at":"2025-06-26T07:31:46.347Z","repository":{"id":58331065,"uuid":"531255407","full_name":"CppPlayground/LTC-LinearTimecode-SMPTE","owner":"CppPlayground","description":"A LinearTimecode decode library for Arduino.cc","archived":false,"fork":false,"pushed_at":"2024-04-10T05:22:49.000Z","size":182,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-25T02:43:55.917Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CppPlayground.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-08-31T20:53:59.000Z","updated_at":"2024-07-12T13:16:10.000Z","dependencies_parsed_at":"2024-04-10T06:28:29.272Z","dependency_job_id":"1ab06307-1d4d-4ab6-b311-687b50b45717","html_url":"https://github.com/CppPlayground/LTC-LinearTimecode-SMPTE","commit_stats":null,"previous_names":["cppplayground/ltc-lineartimecode-smpte"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CppPlayground/LTC-LinearTimecode-SMPTE","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CppPlayground%2FLTC-LinearTimecode-SMPTE","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CppPlayground%2FLTC-LinearTimecode-SMPTE/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CppPlayground%2FLTC-LinearTimecode-SMPTE/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CppPlayground%2FLTC-LinearTimecode-SMPTE/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CppPlayground","download_url":"https://codeload.github.com/CppPlayground/LTC-LinearTimecode-SMPTE/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CppPlayground%2FLTC-LinearTimecode-SMPTE/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262022036,"owners_count":23246238,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-10T12:27:51.705Z","updated_at":"2025-06-26T07:31:46.321Z","avatar_url":"https://github.com/CppPlayground.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LTC LinearTimecode (SMPTE)\nA LinearTimecode decode library for [Arduino.cc](https://www.arduino.cc)\n\nUse this library to decode linear timecodes. You can generate such timecodes for example on the [elteesee](https://elteesee.pehrhovey.net) website made by [pehrhovey](http://pehrhovey.net/blog/about/). You can find more references in [this wikipedia](https://en.wikipedia.org/wiki/Linear_timecode) article.\n\n\u003e Skip to [How to use the library](#how-to-use-the-library)\n\n----\n\n### What is LTC?\n\n\"LTC\" stands for \"Linear Timecode\" and is used to encode/decode timecode data in an audio signal. Basically you have an audio signal that runs synchronously with the music or the film and in which the timecode is stored as a bit sequence. You can also store the date in a timecode, but I'll just cover the time for now.\n\n----\n\n### How does LTC work?\n\nThe time code consists of 8 bytes and a fixed sync word at the end. So 10 bytes in total. The fixed sync word at the end is used to tell the decoder that the sequence has ended.\n\u003e A long bit period corresponds to a 0 bit \u003cbr\u003e A double short bit period corresponds to a 1 bit\n\n####  Example for one frame\n\n\u003e This example shows the timecode `00:00:00.00`\n\n![signwave](https://github.com/Mqxx/LTC-LinearTimecode-SMPTE/blob/main/assets/signwave.svg \"Signwave\")\n\n\u003e [Raw image](https://raw.githubusercontent.com/Mqxx/LTC-LinearTimecode-SMPTE/main/assets/signwave.svg)\n\n#### Which byte does what?\n\nByte    | Bit       | Visuel        | Meaning                    \n:---:   |:---:      |:---:          |:---                        \nA       | `0` - `3` | `--:--:--.-X` | Frame number units (0–9)   \nB       | `0` - `3` | `--:--:--.X-` | Frame number tens (0-2)    \nC       | `0` - `3` | `--:--:-X.--` | Seconds number units (0–9) \nD       | `0` - `3` | `--:--:X-.--` | Seconds number tens (0–5)  \nE       | `0` - `3` | `--:-X:--.--` | Minutes number units (0-9) \nF       | `0` - `3` | `--:X-:--.--` | Minutes number tens (0-5)  \nG       | `0` - `3` | `-X:--:--.--` | Hours number units (0-9)   \nH       | `0` - `3` | `X-:--:--.--` | Hours number tens (0-2)    \nI       | `0` - `7` |               | Sync word                  \nJ       | `0` - `7` |               | Sync word                  \n\n\u003e Binary decimal numbers [wiki](https://en.wikipedia.org/wiki/Binary_number)\n\n----\n\n### How does the library decode the timecode?\n\n#### Standards\n\nFirst, there are different timecode standards, which differ in the number of frames or the length of a frame as you can see on the [elteesee](https://elteesee.pehrhovey.net) website.\n- 23.976 F \u003cbr\u003e\n- 24 F \u003cbr\u003e\n- 25 F \u003cbr\u003e\n- 29.97ndf (no drop frame) \u003cbr\u003e\n- 30 F\n\n#### Calculate one bit lenght\n\nTo calculate how long one bit lasts, we need to do a bit of math. Got it? A *bit* of math? Nahh lets go on 😅:\n\n```ino\n// convert framerate to ms\nfloat framerate = 25.00;\nfloat ms = 1000 / framerate;\n\n// now calculate how long one bit is\n// a frame consists of 80 bits\n// this gives us back how long one bit is in ms\nfloat oneBit = ms / 80;\n\n// convert ms to µs and cast to int and we have the bit length in µs\nconst int bitLength = int(oneBit * 1000);\n```\n\nNow the library just waits for an interrupt. An interrupt occurs when the sine wave crosses 0. Then the library checks the time difference between the two interrupts. A short time between two interrupts means that a 1 bit has arrived, and a long time between two interrupts means that a 0 bit has arrived.\n\n----\n\n### How to use the library?\n\n#### Syntax\n\n###### constructor\n\n```ino\nLinearTimecode::LinearTimecode(LinearTimecode::frameTypes frameType);\n```\n`enum frameType` : `{ FRAME_23_976, FRAME_24, FRAME_25, NO_DROP_FRAME_29_97, FRAME_30 }`\n\n\u003cbr\u003e\n\n```ino\nLinearTimecode::LinearTimecode(const unsigned int frameDuration);\n```\n`const unsigned int frameDuration` : `duration`\n\n\u003cbr\u003e\n\n###### methodes\n\n```ino\nconst int LinearTimecode::getBitLength();\n```\n\u003e Returns the bit length of one bit.\n\n\u003cbr\u003e\n\n```ino\nuint8_t LinearTimecode::getByteBuffer(const unsigned int index);\n```\n`const unsigned int index` : `index`\n\u003e Returns the byte buffer at the specified index.\n\n\u003cbr\u003e\n\n```ino\nfloat LinearTimecode::getFramerate();\n```\n\u003e Returns the set frame rate as a floating point number\n\n\u003cbr\u003e\n\n```ino\nconst int LinearTimecode::getFrames();\n```\n\u003e Returns the current frame\n\n\u003cbr\u003e\n\n```ino\nconst int LinearTimecode::getSeconds();\n```\n\u003e Returns the current second\n\n\u003cbr\u003e\n\n```ino\nconst int LinearTimecode::getMinutes();\n```\n\u003e Returns the current minute\n\n\u003cbr\u003e\n\n```ino\nconst int LinearTimecode::getHours();\n```\n\u003e Returns the current hour\n\n\u003cbr\u003e\n\n```ino\nString LinearTimecode::getTimecode(LinearTimecode::formats format);\n```\n`enum format` : `{ FORMAT_DOT, FORMAT_COLON, FORMAT_DOT_COLON, FORMAT_SPACE }`\n\u003e Returns the timecode in a string format\u003cbr\u003e\n\u003e Format              | Visual\n\u003e :---                |:---:\n\u003e `FORMAT_DOT`        | `HH.MM.SS.FF`\n\u003e `FORMAT_COLON`      | `HH:MM:SS:FF`\n\u003e `FORMAT_DOT_COLON`  | `HH:MM:SS.FF`\n\u003e `FORMAT_SPACE`      | `HH MM SS FF`\n\n\u003cbr\u003e\n\n```ino\nvoid LinearTimecode::onEdgeChange();\n```\n\u003e Needs to be executed on an interrupt change on the audio pin\n\n\u003cbr\u003e\n\n```ino\nvoid LinearTimecode::onSync(void (*callback)());\n```\n`void (*callback)()` : `function to execute`\n\u003e Gets called when the sync pattern is detected\n\n\u003cbr\u003e\n\n```ino\nvoid LinearTimecode::setShortEdgeDuration(const unsigned int min, const unsigned int max);\n```\n`const unsigned int min` : `the minimum short edge duration`\u003cbr\u003e\n`const unsigned int max` : `the maximum short edge duration`\n\u003e Set the minimum and maximum duration of the short edge\n\n\u003cbr\u003e\n\n```ino\nvoid LinearTimecode::setLongEdgeDuration(const unsigned int min, const unsigned int max);\n```\n`const unsigned int min` : `the minimum long edge duration`\u003cbr\u003e\n`const unsigned int max` : `the maximum long edge duration`\n\u003e Set the minimum and maximum duration of the long edge\n\n\u003cbr\u003e\n\n```ino\nvoid LinearTimecode::setSyncPattern(word pattern);\n```\n`word pattern` : `sync pattern`\n\u003e Set the sync pattern\n\n\u003cbr\u003e\n\n#### Example\n\n###### code\n\n```ino\n// include\n// include the libary\n#include \u003cLinearTimecode.h\u003e\n\n// define\n// the audio in pin needs to be an change intrrupt pin!\n#define AUDIO_IN 2\n\n// Create a new LinearTimecode class instance (I'll call it \"ltc\") with a frame rate of 25 frames\nLinearTimecode ltc(ltc.FRAME_30);\n\n// the setup function\nvoid setup() {\n  // begin serial\n  Serial.begin(115200);\n\n  // attach the interrupt pin to pin 2\n  attachInterrupt(2, [](){\n    \n    // call the onEdgeChange() method of your class instance\n    // this needs to be in a lambda function!\n    ltc.onEdgeChange();\n  }, CHANGE);\n  \n  // call the onSync() method of your class instance\n  ltc.onSync([](){\n    \n    // print the result in the console\n    Serial.println(ltc.getTimecode(ltc.FORMAT_DOT_COLON));\n  });\n}\n\nvoid loop() {\n\n}\n\n```\n\n###### output\n\n```\n10:03:12.13\n```\n\u003e Example timecode\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcppplayground%2Fltc-lineartimecode-smpte","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcppplayground%2Fltc-lineartimecode-smpte","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcppplayground%2Fltc-lineartimecode-smpte/lists"}