ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
9 июля
1595354 Топик полностью
Связанные сообщения
ArduinoAudio
Думаю, для начала лучше определиться - хочется хороший усилитель для наушников, или просто "что-то ламповое"? В первом случае, и...2025-09-08
Пятничное запоздалое - мозги дымятся от всяких CPU CPLD, давно хотел сделать что то ламповое, чтобы релаксировать :) Вот думаю -...2025-09-08
Коллеги, а расскажите, кто знает, про Ардуину. Нужен быстрый ликбез, что там как устроено. А то я пришёл к выводу все их доки мн...2023-09-17
УМЗЧ [Симметрон]2022-09-06
Старые колонки [Technics SB-10]. Как ни странно, популярны у торговцев БУ. 1979. Расчеты методом конечных элементов, блин...2022-08-27
Собственно, мысль поискать передовые решения низких искажений в среде аудиофилов - здравая. Хоть эти люди часто не от мира сего,...2022-08-20
сабвуфер, всего лишь 8 кВт2021-12-28
Чуток библиографии МРБ:2020-04-15
Статьи - просто шедевр!2020-04-08
[ТруЪ Audio] Сводный системный по методологии и схемотехнике аудиодиофильства.2020-04-08
Arduino. Знатоки, киньте ссылку на какой-нить наборчик для ребенка 14лет 2015-12-23
klen (Сегодня, 21:43, просмотров: 368)
какая прелЭсть этот buzzer + RTTTL: залип на сутки... акацца мы все композиторы, то что музыканты это талантливые люди - в общем то вранье, что такое ноты и как ими писать музло выучил за пол часа 

Итак! у меня опять новое "чудесатое открытие". может кому нибудь такому же, как я неотесанному внезапно тоже зайдет.

к не очень громким и не совсем противным звукам я как и все лесные звери отношусь терпимо, к музыке я отношусь также как свин к апельсинам!

даже с плеером и тампонами в ушах я никогда не ходил.


и вот... делаю я такой свой очередной девайс, и возникли у меня неудобства, а именно - девайс это антенный блок, радиоприемник а между ними N-1 метров кабеля. антенна должна быть на окне. а приемник с отладчиком у меня на столе. антенна получилась такой расчудесной, что изменение температуры в комнате при открытии окна приводит к вываливанию с резонанса. нужно ручками подстраивать - макет из гамна и палок, че тут скажешь.

сначала я на oled-экранчике на девайсе нарисовал спектроанализатор - чтоб видеть АЧХ и куда она съезжает при кручении-верчении конденсаторов. на какое то время это хватило.... но далеко и плохо видно, все равно нужно крутить одно, смотреть в другую сторону. короче неудобно. И долго бы я так умчался если б в помойке случайно не нашел писчалку от старого PC. дальше по экспоненте..


внезапно обнаруживаем в соседней галактике прото-жизнь, древнюю как первые звезды видимой части космоса - а именно Ring Tone Text Transfer Language (RTTTL)

выглядить это так

imperial:d=4,o=5,b=100:a,a,a,8f,16c6,a,8f,16c6,2a,e6,e6,e6,8f6,16c6,g#,8f,16c6,2a

нотная дорожка с настроками октавы темпа и длительности , это мелодия из кина "звездных войн", все ее знают.


придумала это Nokia еще тогда тогда....

это были времена зарождения первых беспозвоночных сотовых телефонов....

мелодии звонков на пищащих сотиках это как раз то самое.


прочитав доку на пол странички я быстро вкодил эту чудесатость, Космос открыл мне еще одно измерение - звук пищалки из печатной платы.

быстренько закодировав нотами и их комбинациями предаваймые биты и события в системе озвучил поведение девайса. Там жеж и попадание в резонанс по тону пищания.


и возрадовался я... и осознал.. могу читать ноты! никогда не умел в теперь таки да! и ниспослано было мне озарение - писать таки тоже!!!! а чёй тоя не композитор чтоль? композитор! только малоизвестный в кругу особо ограниченных лиц.

двое суток залипал и не мог отлипнуть от сочинения пищащего монотонового музла! токо токо отпустило. штырит сильно, но надеюсь не очень заразно.


короче, друззя мои - кто не пробывал это, рекомендую попробывать и втащить в сои девайсы - удобно.

1 ) вики вверху привел. продублирую тут. Ring Tone Text Transfer Language (RTTTL)

2) большая база известных и популярных мелодий

3) потребуется код который парсит нотную строку и два таймера - один для меандра звукового тона, текущей ноты, тамер длительности ноты, через gpio вывод на пищалку. Парсер по сути из строки вычитывает частоту и длительность тона в музыкальной-нотной нотации.

4) для отладки и проверки есть онлайн проигрователь

5) стоить это дешевле копейки.. а радости сколько!



ниже приведу свой С++ код ( парсер/проигрователь ) который накидал пока читал как это работает, попутно выдирая куски с github, там такого добра для дурины много :)

? 
/* * rtttl.h * * Created on: 5 июл. 2026 г. * Author: klen */ #pragma once namespace sound { static constexpr uint16_t note_mute= 0 ; static constexpr uint16_t note_b0 = 31 ; static constexpr uint16_t note_c1 = 33 ; static constexpr uint16_t note_cs1 = 35 ; static constexpr uint16_t note_d1 = 37 ; static constexpr uint16_t note_ds1 = 39 ; static constexpr uint16_t note_e1 = 41 ; static constexpr uint16_t note_f1 = 44 ; static constexpr uint16_t note_fs1 = 46 ; static constexpr uint16_t note_g1 = 49 ; static constexpr uint16_t note_gs1 = 52 ; static constexpr uint16_t note_a1 = 55 ; static constexpr uint16_t note_as1 = 58 ; static constexpr uint16_t note_b1 = 62 ; static constexpr uint16_t note_c2 = 65 ; static constexpr uint16_t note_cs2 = 69 ; static constexpr uint16_t note_d2 = 73 ; static constexpr uint16_t note_ds2 = 78 ; static constexpr uint16_t note_e2 = 82 ; static constexpr uint16_t note_f2 = 87 ; static constexpr uint16_t note_fs2 = 93 ; static constexpr uint16_t note_g2 = 98 ; static constexpr uint16_t note_gs2 = 104 ; static constexpr uint16_t note_a2 = 110 ; static constexpr uint16_t note_as2 = 117 ; static constexpr uint16_t note_b2 = 123 ; static constexpr uint16_t note_c3 = 131 ; static constexpr uint16_t note_cs3 = 139 ; static constexpr uint16_t note_d3 = 147 ; static constexpr uint16_t note_ds3 = 156 ; static constexpr uint16_t note_e3 = 165 ; static constexpr uint16_t note_f3 = 175 ; static constexpr uint16_t note_fs3 = 185 ; static constexpr uint16_t note_g3 = 196 ; static constexpr uint16_t note_gs3 = 208 ; static constexpr uint16_t note_a3 = 220 ; static constexpr uint16_t note_as3 = 233 ; static constexpr uint16_t note_b3 = 247 ; static constexpr uint16_t note_c4 = 262 ; // до static constexpr uint16_t note_cs4 = 277 ; static constexpr uint16_t note_d4 = 294 ; // ре static constexpr uint16_t note_ds4 = 311 ; static constexpr uint16_t note_e4 = 330 ; // ми static constexpr uint16_t note_f4 = 349 ; // фа static constexpr uint16_t note_fs4 = 370 ; static constexpr uint16_t note_g4 = 392 ; // соль static constexpr uint16_t note_gs4 = 415 ; static constexpr uint16_t note_a4 = 440 ; // ля static constexpr uint16_t note_as4 = 466 ; static constexpr uint16_t note_b4 = 494 ; // си static constexpr uint16_t note_c5 = 523 ; static constexpr uint16_t note_cs5 = 554 ; static constexpr uint16_t note_d5 = 587 ; static constexpr uint16_t note_ds5 = 622 ; static constexpr uint16_t note_e5 = 659 ; static constexpr uint16_t note_f5 = 698 ; static constexpr uint16_t note_fs5 = 740 ; static constexpr uint16_t note_g5 = 784 ; static constexpr uint16_t note_gs5 = 831 ; static constexpr uint16_t note_a5 = 880 ; static constexpr uint16_t note_as5 = 932 ; static constexpr uint16_t note_b5 = 988 ; static constexpr uint16_t note_c6 = 1047 ; static constexpr uint16_t note_cs6 = 1109 ; static constexpr uint16_t note_d6 = 1175 ; static constexpr uint16_t note_ds6 = 1245 ; static constexpr uint16_t note_e6 = 1319 ; static constexpr uint16_t note_f6 = 1397 ; static constexpr uint16_t note_fs6 = 1480 ; static constexpr uint16_t note_g6 = 1568 ; static constexpr uint16_t note_gs6 = 1661 ; static constexpr uint16_t note_a6 = 1760 ; static constexpr uint16_t note_as6 = 1865 ; static constexpr uint16_t note_b6 = 1976 ; static constexpr uint16_t note_c7 = 2093 ; static constexpr uint16_t note_cs7 = 2217 ; static constexpr uint16_t note_d7 = 2349 ; static constexpr uint16_t note_ds7 = 2489 ; static constexpr uint16_t note_e7 = 2637 ; static constexpr uint16_t note_f7 = 2794 ; static constexpr uint16_t note_fs7 = 2960 ; static constexpr uint16_t note_g7 = 3136 ; static constexpr uint16_t note_gs7 = 3322 ; static constexpr uint16_t note_a7 = 3520 ; static constexpr uint16_t note_as7 = 3729 ; static constexpr uint16_t note_b7 = 3951 ; static constexpr uint16_t note_c8 = 4186 ; static constexpr uint16_t note_cs8 = 4435 ; static constexpr uint16_t note_d8 = 4699 ; static constexpr uint16_t note_ds8 = 4978 ; static constexpr uint16_t notes[] = { note_mute,// #0 тишина note_c4, // #1 note_cs4, // note_d4, // note_ds4, // note_e4, // note_f4, // note_fs4, // note_g4, // note_gs4, // note_a4, // note_as4, // note_b4, // #12 note_c5, // #13 note_cs5, // note_d5, // note_ds5, // note_e5, // note_f5, // note_fs5, // note_g5, // note_gs5, // note_a5, // note_as5, // note_b5, // #24 note_c6, // #25 note_cs6, // note_d6, // note_ds6, // note_e6, // note_f6, // note_fs6, // note_g6, // note_gs6, // note_a6, // note_as6, // note_b6, // #36 note_c7, // #37 note_cs7, // note_d7, // note_ds7, // note_e7, // note_f7, // note_fs7, // note_g7, // note_gs7, // note_a7, // note_as7, // note_b7, // #48 2*note_c7, // #49 2*note_cs7, // 2*note_d7, // 2*note_ds7, // 2*note_e7, // 2*note_f7, // 2*note_fs7, // 2*note_g7, // 2*note_gs7, // 2*note_a7, // 2*note_as7, // 2*note_b7, // #60 0 // #61 }; static constexpr string_view melody[]= { /*0 static constexpr string_view rtttl_imperial*/ {":d=4,o=5,b=100:a,a,a,8f,16c6,a,8f,16c6,2a,e6,e6,e6,8f6,16c6,g#,8f,16c6,2a,"}, /*1 static constexpr string_view rtttl_boomer*/ {":d=4,o=5,b=140:8e,g,8p,2p,8g,e,8p,2p,8a,8g,8a,8g,8a,8g,8a,8g,8a,b,8p,2p"}, /*2 static constexpr string_view rtttl_lhx*/ {":d=4,o=5,b=125:8e,8e,8e,2e,8e,8e,8e,2e,8e,8e,8e,8f#,8g,8f#,8e,8d,8e,8e,8e,2e,8e,8e,8e,2e,8e,8e,8e,8f#,8g,8f#,8e,8d,8b4,8b4,8b4,2b4,8b4,8b4,8b4,2b4,8b4,8b4,8b4,8c,8d,8c,8b4,8a4,8b4,8b4,8b4,2b4,8b4,8b4,8b4,2b4,8e,8e,8e,8f#,8g,8f#,8e,8d"}, /*3 static constexpr string_view rtttl_lhx2*/ {":d=4,o=5,b=125:8e,8b,8a,8b,8d6,2b.,8p,8e,8b,8a,8b,8e6,2b.,8p,8g6,8f#6,8e6,8d6,8e6,2b.,8p,8g6,8f#6,8e6,8d6,8f#6,2b.,8p,8e,8b,8a,8b,8d6,2b.,8p,8e,8b,8a,8b,8e6,2b.,8p,8e6,2b"}, /*4 static constexpr string_view rtttl_f29Retaliator*/{":d=4,o=5,b=125:8e,8b,8a,8b,8d6,2b,8e,8b,8a,8b,8e6,2b,8g6,8f#6,8e6,8d6,8e6,2b,8g6,8f#6,8e6,8d6,8f#6,2b,8e,8b,8a,8b,8d6,2b,8e,8b,8a,8b,8e6,1b"}, /*5 static constexpr string_view rtttl_goodbadugly0*/ {":d=4,o=5,b=56:8a,8d6,8a,8d6,8a,16g,16a,8g,8- ,8a,8d6,8a,8d6,8f,16g,16f,2d,8c6,8f6,8c6,8f6,8c6,16a#,16c6,8a#,8- ,8c6,8f6,8c6,8f6,8g,16a,16g,2d"}, /*6 static constexpr string_view rtttl_goodbadugly1*/ {":d=4,o=5,b=56:32p,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,d#,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,c#6,32a#,32d#6,32a#,32d#6,8a#.,16f#.,32f.,32d#.,c#,32a#,32d#6,32a#,32d#6,8a#.,16g#.,d#"}, /*7 static constexpr string_view rtttl_kalinka*/ {":d=4,o=5,b=160:e6,8b,8c6,8d6,16e6,16d6,8c6,8b,a,8a,8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,2a,8p,d6,8f6,a6,8g6,8f6,e6,8e6,8c6,e6,8d6,8c6,b,8b,8c6,d6,e6,c6,a,a."}, /*8 static constexpr string_view rtttl_xfiles*/ {":d=4,o=5,b=125:e,b,a,b,d6,2b.,1p,e,b,a,b,e6,2b.,1p,g6,f#6,e6,d6,e6,2b.,1p,g6,f#6,e6,d6,f#6,2b.,1p,e,b,a,b,d6,2b.,1p,e,b,a,b,e6,2b.,1p,e6,2b."}, /*9 static constexpr string_view rtttl_missionimp*/ {":d=16,o=6,b=95:32d,32d#,32d,32d#,32d,32d#,32d,32d#,32d,32d,32d#,32e,32f,32f#,32g,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,g,8p,g,8p,a#,p,c7,p,g,8p,g,8p,f,p,f#,p,a#,g,2d,32p,a#,g,2c#,32p,a#,g,2c,a#5,8c,2p,32p,a#5,g5,2f#,32p,a#5,g5,2f,32p,a#5,g5,2e,d#,8d"}, /*10 static constexpr string_view rtttl_takeoneme*/ {":d=8,o=5,b=160,b=160:f#,f#,f#,d,p,b4,p,e,p,e,p,e,g#,g#,a,b,a,a,a,e,p,d,p,f#,p,f#,p,f#,e,e,f#,e,f#,f#,f#,d,p,b4,p,e,p,e,p,e,g#,g#,a,b,a,a,a,e,p,d,p,f#,p,f#,p,f#,e,e5"}, /*11 static constexpr string_view rtttl_popcorn*/ {":d=16,o=5,b=160,b=160:a,p,g,p,a,p,e,p,c,p,e,p,8a4,8p,a,p,g,p,a,p,e,p,c,p,e,p,8a4,8p,a,p,b,p,c6,p,b,p,c6,p,a,p,b,p,a,p,b,p,g,p,a,p,g,p,a,p,f,8a,8p,a,p,g,p,a,p,e,p,c,p,e,p,8a4,8p,a,p,g,p,a,p,e,p,c,p,e,p,8a4,8p,a,p,b,p,c6,p,b,p,c6,p,a,p,b,p,a,p,b,p,g,p,a,p,g,p,a,p,b,4c6"}, } ; template< typename io_t, const size_t _buff_size, const size_t common_tempo, const size_t common_octave, const size_t common_bpm > class rtttl_t { public: __ai__ rtttl_t() noexcept { io_t::init(); } __ai__ void begin(uint8_t ooff = 0) noexcept { header(ooff); // чтение заголовка bool not_last_note ; do { note_t n ; not_last_note = next_note(n); // итерация по нотам if ( n.tone ) { io_t::tone( n.tone ); // установка чатоты меандра io_t::enable(); // разрешение генерации тона ноты } io_t::delay(n.duration); // установка длительности ноты io_t::disable(); // запрещение генерации тона ноты } while (not_last_note) ; } protected: struct note_t { uint16_t tone ; // частота тона ноты [Гц], если 0 - отсутствие звука uint16_t duration ; // длительность ноты [мсек] }; struct param_t { char param ; // параметр int32_t duration ; // значение }; static constexpr size_t buff_size = _buff_size; __ai__ void header(uint8_t ooff) noexcept { p = buff ; end = buff + size ; default_tempo = common_tempo; default_octave = common_octave; size_t bpm = common_bpm; octave_offset = ooff ; get_num(':') ; // пропуск имени size_t num ; if ( *p == 'd') if ((num = get_num(',', 2)) > 0) default_tempo = num; // get default duration if ( *p == 'o') if ( num = get_num(',', 2); num >= 3 && num <= 7) default_octave = num; // get default octave if ( *p == 'b') bpm = get_num(':', 2) ;// get BPM // BPM usually expresses the number of quarter notes per minute wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) } __ai__ bool next_note(note_t& n) noexcept { // чтение длительности if ( size_t num = get_num() ) n.duration = wholenote / num; else n.duration = wholenote / default_tempo; // we will need to check if we are a dotted note after // чтение ноты char note; switch ( *p ) { case 'c': note = 1; break; case 'd': note = 3; break; case 'e': note = 5; break; case 'f': note = 6; break; case 'g': note = 8; break; case 'a': note = 10; break; case 'b': note = 12; break; case 'p': default: note = 0; } p++; if ( *p == '#') { note++ ; p++; } if ( *p == '.') { n.duration += n.duration / 2; p++; } // чтение октавы size_t octave ; if ( !(octave=get_num()) ) octave = default_octave; octave += octave_offset; get_num(',') ; // сдвиг на следующую ноту или конец if (note) [[likely]] n.tone = notes[ (octave - 4) * 12 + note ] ; else n.tone = 0 ; return p < end ; } __ai__ auto get_num( const char skip = 0, const size_t shift = 0 ) noexcept { p+=shift ; size_t val = 0; while ( kgp_sdk_libc::isdigit( *p ) && (p < end) ) { val = (val * 10) + ( *p - '0'); p++; } if (skip) { while( (*p != skip) && (p < end)) p++; p++ ; } return val ; } char buff[buff_size] ; size_t size ; private : char* p ; // указатель на текущий байт char* end ; // указатель на байт, следующи й за концом блока данных char default_tempo; char default_octave; size_t wholenote ; uint8_t octave_offset ; } ; }// namespace sound



с ходу вы его врядли вкарячите к себе - быстрее постотреть как оно у меня работает и по месту свое накидать. код сырой , никаких проверок на ошибки в нотной записи.

функция begin прогрывает нотную строку. ноту за нотой пока они не кончатся в буфере. перед ее вызовом в buff доджна быть помещена строка, а в size ее длинна.


теперь мой девайс при загрузке проигрывает вот этО:

":d=4,o=5,b=56:32p,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,d#,32a#,32d#6,32a#,32d#6,8a#.,16f#.,16g#.,c#6,32a#,32d#6,32a#,32d#6,8a#.,16f#.,32f.,32d#.,c#,32a#,32d#6,32a#,32d#6,8a#.,16g#.,d#"


угадаете что это?