#include "pke-at-common.hpp" #include "pke-at-settings.hpp" #include "pke/audio-types.hpp" void pke_at_bpm_reset(uint8_t bpm) { g_at.bpm.last = bpm; g_at.bpm.target = bpm; g_at.bpm.current = bpm; g_at.bpm.lerp_delta = 0.f; g_at.bpm.lerp_delta_duration = 0.f; g_at.bpm.delta_per_beat = 60.f / (double)bpm; g_at.bpm.delta_since_last_beat = BEEP_IMMEDIATELY_VAL; g_at.mtrnm.beat = 0; g_at.mtrnm.beats_per_bar = 4; } AssetHandle pke_at_audio_get_or_generate_sawtooth(double pitch_freq, double duration) { uint32_t u; uint32_t len; float *bytes; float phase; float phase_increment; pke_asset_details details{}; AssetHandle handle; AssetKey key; snprintf(key, AssetKeyLength, "saw%.5u;%.2f", (uint32_t)pitch_freq, duration); fprintf(stdout, "sawtooth: %s%c\n", key, '\0'); handle = AM_GetHandle(key); if (handle != AssetHandle_MAX) { return handle; } len = std::ceil(PKE_AUDIO_BITRATE * duration); bytes = pk_new_arr(len, g_at.mem.bkt_transient); if (bytes == nullptr) { throw "[pke_at_audio_get_or_generate_sawtooth] failed to alloc"; } phase = 0.0f; phase_increment = pitch_freq / float(PKE_AUDIO_BITRATE); for (u = 0; u < len; ++u) { bytes[u] = 2.f * (phase - floor(phase + 0.5f)); phase += phase_increment; if (phase >= 1.f) phase -= 1.f; } // TODO // details.audio. handle = AM_Register(key, PKE_ASSET_TYPE_AUDIO, bytes, len, 64, &details); return handle; } int case_insensitive_equal(const char *lhs, const char *rhs) { while (*lhs && *rhs) { if (tolower((unsigned char)*lhs) != tolower((unsigned char)*rhs)) { return 0; } lhs++; rhs++; } return *lhs == *rhs; } PKE_AT_KEY_INDEX parse_key_from_string(const char *key) { switch (key[0]) { case 'c': case 'C': if (strlen(key) == 1 || key[1] != '#') { return PKE_AT_KEY_INDEX_C; } if (key[1] == '#') { return PKE_AT_KEY_INDEX_C_SHARP; } break; case 'd': case 'D': if (strlen(key) == 1 || (key[1] != 'b' && key[1] != '#')) { return PKE_AT_KEY_INDEX_D; } if (key[1] == 'b') { return PKE_AT_KEY_INDEX_D_FLAT; } if (key[1] == '#') { return PKE_AT_KEY_INDEX_D_SHARP; } break; case 'e': case 'E': if (strlen(key) == 1 || key[1] != 'b') { return PKE_AT_KEY_INDEX_E; } if (key[1] == 'b') { return PKE_AT_KEY_INDEX_E_FLAT; } break; case 'f': case 'F': if (strlen(key) == 1 || (key[1] != 'b' && key[1] != '#')) { return PKE_AT_KEY_INDEX_F; } if (key[1] == '#') { return PKE_AT_KEY_INDEX_F_SHARP; } break; case 'g': case 'G': if (strlen(key) == 1 || (key[1] != 'b' && key[1] != '#')) { return PKE_AT_KEY_INDEX_G; } if (key[1] == 'b') { return PKE_AT_KEY_INDEX_G_FLAT; } if (key[1] == '#') { return PKE_AT_KEY_INDEX_G_SHARP; } break; case 'a': case 'A': if (strlen(key) == 1 || (key[1] != 'b' && key[1] != '#')) { return PKE_AT_KEY_INDEX_A; } if (key[1] == 'b') { return PKE_AT_KEY_INDEX_A_FLAT; } if (key[1] == '#') { return PKE_AT_KEY_INDEX_A_SHARP; } break; case 'b': case 'B': if (strlen(key) == 1 || key[1] != 'b') { return PKE_AT_KEY_INDEX_B; } if (key[1] == 'b') { return PKE_AT_KEY_INDEX_B_FLAT; } default: break; } return PKE_AT_KEY_INDEX_NONE; } PKE_AT_SECTION_TYPE_INDEX parse_section_type_from_string(const char *section) { if (case_insensitive_equal(section, "verse")) { return PKE_AT_SECTION_TYPE_INDEX_VERSE; } if (case_insensitive_equal(section, "chorus")) { return PKE_AT_SECTION_TYPE_INDEX_CHORUS; } if (case_insensitive_equal(section, "bridge")) { return PKE_AT_SECTION_TYPE_INDEX_BRIDGE; } if (case_insensitive_equal(section, "intro")) { return PKE_AT_SECTION_TYPE_INDEX_INTRO; } if (case_insensitive_equal(section, "outro")) { return PKE_AT_SECTION_TYPE_INDEX_OUTRO; } if (case_insensitive_equal(section, "end")) { return PKE_AT_SECTION_TYPE_INDEX_END; } if (case_insensitive_equal(section, "ending")) { return PKE_AT_SECTION_TYPE_INDEX_ENDING; } if (case_insensitive_equal(section, "instrumental")) { return PKE_AT_SECTION_TYPE_INDEX_INSTRUMENTAL; } if (case_insensitive_equal(section, "interlude")) { return PKE_AT_SECTION_TYPE_INDEX_INTERLUDE; } if (case_insensitive_equal(section, "refrain")) { return PKE_AT_SECTION_TYPE_INDEX_REFRAIN; } if (case_insensitive_equal(section, "tag")) { return PKE_AT_SECTION_TYPE_INDEX_TAG; } return PKE_AT_SECTION_TYPE_INDEX_NONE; }