virtual void SetEnvelopeType(uint_t type) { if (Command* cmd = Patterns.GetChannel().FindCommand(ENVELOPE)) { cmd->Param1 = int_t(type); } else { Patterns.GetChannel().AddCommand(ENVELOPE, int_t(type), -1); } }
virtual void SetEnvelopeTone(uint_t tone) { if (Command* cmd = Patterns.GetChannel().FindCommand(ENVELOPE)) { cmd->Param2 = int_t(tone); } else { //strange situation Patterns.GetChannel().AddCommand(ENVELOPE, -1, int_t(tone)); } }
virtual Container::Ptr Decode(const Binary::Container& rawData) const { if (!Player->Match(rawData)) { return Container::Ptr(); } const Binary::TypedContainer typedData(rawData); const std::size_t availSize = rawData.Size(); const std::size_t playerSize = CompiledPT24::PLAYER_SIZE; const CompiledPT24::Player& rawPlayer = *typedData.GetField<CompiledPT24::Player>(0); const uint_t dataAddr = fromLE(rawPlayer.DataAddr); if (dataAddr < playerSize) { Dbg("Invalid compile addr"); return Container::Ptr(); } const CompiledPT24::RawHeader& rawHeader = *typedData.GetField<CompiledPT24::RawHeader>(playerSize); const uint_t patternsCount = CompiledPT24::GetPatternsCount(rawHeader, availSize - playerSize); if (!patternsCount) { Dbg("Invalid patterns count"); return Container::Ptr(); } const uint_t compileAddr = dataAddr - playerSize; Dbg("Detected player compiled at %1% (#%1$04x) with %2% patterns", compileAddr, patternsCount); const std::size_t modDataSize = std::min(CompiledPT24::MAX_MODULE_SIZE, availSize - playerSize); const Binary::Container::Ptr modData = rawData.GetSubcontainer(playerSize, modDataSize); const Formats::Chiptune::PatchedDataBuilder::Ptr builder = Formats::Chiptune::PatchedDataBuilder::Create(*modData); //fix samples/ornaments offsets for (uint_t idx = offsetof(CompiledPT24::RawHeader, SamplesOffsets); idx != offsetof(CompiledPT24::RawHeader, PatternsOffset); idx += 2) { builder->FixLEWord(idx, -int_t(dataAddr)); } //fix patterns offsets for (uint_t idx = fromLE(rawHeader.PatternsOffset), lim = idx + 6 * patternsCount; idx != lim; idx += 2) { builder->FixLEWord(idx, -int_t(dataAddr)); } const Binary::Container::Ptr fixedModule = builder->GetResult(); if (Formats::Chiptune::Container::Ptr fixedParsed = Decoder->Decode(*fixedModule)) { return CreatePackedContainer(fixedParsed, playerSize + fixedParsed->Size()); } Dbg("Failed to parse fixed module"); return Container::Ptr(); }
template<> int_t random<int_t>(int_t const & max) { #if USE_GMPLIB return int_t(random_source.get_z_range(max._data + 1)); #else return random__int<int_t>(max); #endif }
TEST(TypeUnifyTest, unify_list_simple_1) { Type t1(TypeType::UNKNOWN); Type int_t(TypeType::INT); Type res(TypeType::LIST, &int_t); EXPECT_TRUE(res.unify(&t1)); EXPECT_TRUE(t1.is_complete()); }
TEST(TypeUnifyTest, unify_list_simple_2) { Type t1(TypeType::UNKNOWN); Type int_t(TypeType::INT); Type res(TypeType::LIST, &int_t); EXPECT_TRUE(t1.unify(&res)); EXPECT_TRUE(t1.is_complete()); EXPECT_TRUE(t1 == TypeType::LIST); EXPECT_TRUE(*t1.subtypes[0] == TypeType::INT); }
int_t reverse( const int_t& n ) { if( n < 0 ) return - reverse( -n ) ; else if( n < 10 ) return n ; else { std::string str = n.str() ; auto pos = str.find_last_not_of('0') ; if( pos != str.size() - 1 ) str = str.substr( 0, pos+1 ) ; return int_t( std::string( str.rbegin(), str.rend() ) ) ; } }
virtual void SetNote(uint_t note) { MutableCell& channel = Patterns.GetChannel(); channel.SetEnabled(true); if (Command* cmd = channel.FindCommand(GLISS_NOTE)) { cmd->Param2 = int_t(note); } else { channel.SetNote(note); } }
TEST(TypeUnifyTest, unify_list_internal_type_1) { Type t1(TypeType::UNKNOWN); Type list_t(TypeType::LIST, &t1); EXPECT_FALSE(list_t.is_complete()); Type int_t(TypeType::INT); EXPECT_TRUE(t1.unify(&int_t)); EXPECT_TRUE(t1.is_complete()); EXPECT_TRUE(list_t.is_complete()); EXPECT_TRUE(list_t == TypeType::LIST); EXPECT_TRUE(*list_t.subtypes[0] == TypeType::INT); }
TEST(TypeUnifyTest, unify_list_list_2) { Type t1(TypeType::UNKNOWN); Type list_t(TypeType::LIST, &t1); Type int_t(TypeType::INT); Type target(TypeType::LIST, &int_t); EXPECT_TRUE(target.unify(&list_t)); EXPECT_TRUE(t1.is_complete()); EXPECT_TRUE(list_t.is_complete()); EXPECT_TRUE(list_t == TypeType::LIST); EXPECT_TRUE(*list_t.subtypes[0] == TypeType::INT); }
int_t bit_reverse(int_t word) { int_t reversed = 0; int_t mask = 0xff; unsigned i, shift; uint8_t byte; static_assert(std::is_integral<int_t>::value, "int_t must be an integral type"); for (i = 0; i < 8*sizeof word; i+=8) { byte = (word & (mask << i)) >> i; shift = 8*sizeof word - (i+8); reversed |= int_t(detail::bit_reverse_byte(byte)) << shift; } return reversed; }
inline Sample::Type ScaledMax(int denom, int divisor) { return Sample::MID + denom * (int_t(Sample::MAX)-Sample::MID) / divisor; }
//from SAMPLE_MIN..SAMPLE_MAX scale to -1.0..+1.0 static float ToFloat(Sample::Type smp) { return float(int_t(smp) - Sample::MID) / (Sample::MAX - Sample::MID); }
static bool Check(Sample::Type data, Sample::Type ref) { return Math::Absolute(int_t(data) - ref) <= THRESHOLD; }
void SynthesizeChannel(ChannelState& dst, AYM::ChannelBuilder& channel, AYM::TrackBuilder& track) { if (!dst.Enabled) { channel.SetLevel(0); return; } const Sample& curSample = Data->Samples.Get(dst.CurrentSampleNum); const Sample::Line& curSampleLine = curSample.GetLine(dst.PosInSample); const Ornament& curOrnament = Data->Ornaments.Get(dst.CurrentOrnamentNum); const Ornament::Line& curOrnamentLine = curOrnament.GetLine(dst.PosInOrnament); //calculate volume addon if (dst.VolSlideCounter >= 2) { dst.VolSlideCounter--; } else if (dst.VolSlideCounter) { dst.VolumeAddon += dst.VolSlideAddon; dst.VolSlideCounter = dst.VolSlideDelay; } dst.VolumeAddon += curSampleLine.VolSlide; dst.VolumeAddon = Math::Clamp<int_t>(dst.VolumeAddon, -15, 15); //calculate tone dst.ToneDeviation += curSampleLine.ToneDeviation; dst.NoteAddon += curOrnamentLine.NoteAddon; const int_t halfTone = int_t(dst.Note) + dst.NoteAddon; const int_t toneAddon = dst.ToneDeviation + dst.Sliding / 16; //apply tone channel.SetTone(halfTone, toneAddon); //apply level channel.SetLevel((dst.Volume + 1) * Math::Clamp<int_t>(dst.VolumeAddon + curSampleLine.Level, 0, 15) / 16); //apply envelope if (dst.Envelope && curSampleLine.EnableEnvelope) { channel.EnableEnvelope(); } //calculate noise dst.CurrentNoise += curOrnamentLine.NoiseAddon; //mixer if (curSampleLine.ToneMask) { channel.DisableTone(); } if (curSampleLine.NoiseMask && curSampleLine.EnableEnvelope) { EnvelopeTone += curSampleLine.Adding; track.SetEnvelopeTone(EnvelopeTone); } else { dst.CurrentNoise += curSampleLine.Adding; } if (!curSampleLine.NoiseMask) { track.SetNoise((dst.CurrentNoise + dst.Sliding / 256) & 0x1f); } else { channel.DisableNoise(); } //recalc positions if (dst.SlidingSteps != 0) { if (dst.SlidingSteps > 0) { if (!--dst.SlidingSteps && LIMITER != dst.SlidingTargetNote) //finish slide to note { dst.Note = dst.SlidingTargetNote; dst.SlidingTargetNote = LIMITER; dst.Sliding = dst.Glissade = 0; } } dst.Sliding += dst.Glissade; } if (dst.PosInSample++ >= curSample.GetLoopLimit()) { if (!dst.BreakSample) { dst.PosInSample = curSample.GetLoop(); } else if (dst.PosInSample >= curSample.GetSize()) { dst.Enabled = false; } } if (dst.PosInOrnament++ >= curOrnament.GetLoopLimit()) { dst.PosInOrnament = curOrnament.GetLoop(); } }
constexpr int_t operator"" _i() { // int is at least 16 bits return int_t(detail::parse_signed<std::int16_t, Digits...>()); }
inline int_t StepToHz(int_t step) { //C-1 frequency is 32.7Hz //step * 32.7 / c-1_step return step * 3270 / int_t(C_1_STEP_GLISS * 100); }
void SynthesizeChannel(ChannelState& dst, AYM::ChannelBuilder& channel, AYM::TrackBuilder& track) { if (!dst.Enabled) { channel.SetLevel(0); return; } const Sample& curSample = Data->Samples.Get(dst.SampleNum); const Sample::Line& curSampleLine = curSample.GetLine(dst.PosInSample); const Ornament& curOrnament = Data->Ornaments.Get(dst.OrnamentNum); //apply tone const int_t halftones = int_t(dst.Note) + curOrnament.GetLine(dst.PosInOrnament); channel.SetTone(halftones, dst.Sliding + curSampleLine.Vibrato); if (curSampleLine.ToneMask) { channel.DisableTone(); } //apply level channel.SetLevel(GetVolume(dst.Volume, curSampleLine.Level)); //apply envelope if (dst.Envelope) { channel.EnableEnvelope(); } //apply noise if (!curSampleLine.NoiseMask) { track.SetNoise(curSampleLine.Noise + dst.NoiseAdd); } else { channel.DisableNoise(); } //recalculate gliss if (dst.SlidingTargetNote != LIMITER) { const int_t absoluteSlidingRange = track.GetSlidingDifference(dst.Note, dst.SlidingTargetNote); const int_t realSlidingRange = absoluteSlidingRange - (dst.Sliding + dst.Glissade); if ((dst.Glissade > 0 && realSlidingRange <= 0) || (dst.Glissade < 0 && realSlidingRange >= 0)) { dst.Note = dst.SlidingTargetNote; dst.SlidingTargetNote = LIMITER; dst.Sliding = dst.Glissade = 0; } } dst.Sliding += dst.Glissade; if (++dst.PosInSample >= curSample.GetSize()) { dst.PosInSample = curSample.GetLoop(); } if (++dst.PosInOrnament >= curOrnament.GetSize()) { dst.PosInOrnament = curOrnament.GetLoop(); } }