Created
September 11, 2020 02:31
-
-
Save xxv/fcba34658d0d04e7f72f3916e48f87e7 to your computer and use it in GitHub Desktop.
TV simulator for FastLED
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <FastLED.h> | |
#include "tv.h" | |
namespace { | |
// Shot durations; the number of frames. | |
const static uint8_t DURATIONS[] = { | |
// Short shot lengths | |
6, 8, 12, 16, 24, 24, 24, 24, | |
// Longer shot lengths | |
24, 24, 24, 24, | |
36, 36, 26, 36, 36, 36, 26, 36, | |
48, 48, 48, 48, 48, 48, 48, 48, | |
72, 72, 72, 96, 120 | |
}; | |
const static uint8_t DURATIONS_LEN = sizeof(DURATIONS) / sizeof(DURATIONS[0]); | |
const static uint8_t DURATIONS_SHORT_LEN = 8; | |
} // namespace | |
/** | |
* Return the next frame to display. If the current shot has finished, a new one | |
* will be generated. | |
*/ | |
CHSV TvSim::GetNextFrame() { | |
if (this->frame_ >= this->shot_length_) { | |
CHSV last_frame = this->shot_[this->frame_ > 0 ? this->frame_ - 1 : 0]; | |
this->GenerateShot(last_frame); | |
this->frame_ = 0; | |
} | |
return this->shot_[this->frame_++]; | |
} | |
void TvSim::GenerateShot(const CHSV start_frame) { | |
CHSV end_frame = blend(this->RandomShotHsv(), start_frame, random8(64)); | |
if (random8(2) == 1) { | |
this->GenerateFlat(end_frame); | |
} else { | |
this->GenerateFade(start_frame, end_frame); | |
} | |
this->AddNoise(); | |
} | |
void TvSim::GenerateFade(const CHSV start_frame, const CHSV end_frame) { | |
this->shot_length_ = this->RandomDurationShort(); | |
fill_gradient(this->shot_, this->shot_length_, start_frame, end_frame); | |
} | |
void TvSim::GenerateFlat(const CHSV end_frame) { | |
this->shot_length_ = this->RandomDuration(); | |
for (uint8_t i = 0; i < this->shot_length_; i++) { | |
this->shot_[i] = end_frame; | |
} | |
} | |
/** | |
* Generate a random TV-like HSV color. | |
*/ | |
CHSV TvSim::RandomShotHsv() { | |
return CHSV(random8(140, 200), random(50, 155), random8(179, 255)); | |
} | |
/** | |
* Add a random amount of simplex noise to the current shot. | |
*/ | |
void TvSim::AddNoise() { | |
uint8_t magnitude_h = random8(25); | |
uint8_t magnitude_s = random8(25); | |
uint8_t magnitude_v = random8(25); | |
for (uint8_t i = 0; i < this->shot_length_; i++) { | |
this->shot_[i] = CHSV(qadd8(this->shot_[i].h, | |
scale8(inoise8(i << 6, 0), magnitude_h)), | |
qadd8(this->shot_[i].s, | |
scale8(inoise8(i << 6, 1 << 6), magnitude_s)), | |
qadd8(this->shot_[i].v, | |
scale8(inoise8(i << 6, 2 << 6), magnitude_v))); | |
} | |
} | |
uint8_t TvSim::RandomChoice(const uint8_t *options, const uint8_t length) { | |
return options[random8(length)]; | |
} | |
uint8_t TvSim::RandomDuration() { | |
return this->RandomChoice(DURATIONS, DURATIONS_LEN); | |
} | |
uint8_t TvSim::RandomDurationShort() { | |
return this->RandomChoice(DURATIONS, DURATIONS_SHORT_LEN); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <FastLED.h> | |
class TvSim { | |
public: | |
static const uint8_t FRAME_DELAY_MS = 41; // 24fps | |
CHSV GetNextFrame(); | |
private: | |
uint8_t frame_ = 0; | |
CHSV shot_[120] = { CHSV(0, 0, 0) }; | |
uint8_t shot_length_ = 0; | |
void GenerateShot(const CHSV start_frame); | |
void GenerateFade(const CHSV start_frame, const CHSV end_frame); | |
void GenerateFlat(const CHSV end_frame); | |
CHSV RandomShotHsv(); | |
void AddNoise(); | |
uint8_t RandomChoice(const uint8_t *options, const uint8_t max); | |
uint8_t RandomDuration(); | |
uint8_t RandomDurationShort(); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment