Skip to content

audioutils: Add RTTTL parsing library#3477

Open
ghnotgood wants to merge 1 commit into
apache:masterfrom
ghnotgood:master
Open

audioutils: Add RTTTL parsing library#3477
ghnotgood wants to merge 1 commit into
apache:masterfrom
ghnotgood:master

Conversation

@ghnotgood
Copy link
Copy Markdown
Contributor

Summary

Add rtttl-c, a simple parsing library, to the audioutils directory.

Impact

Developers may implement a procedure that makes sound

void
play_tone(struct rtttl_tone tone)
{
	/* TODO */
}

and then play a sound encoded in the RTTTL string ("..." in the following)

rtttl_play("...", play_tone);

Testing

The testing code is

void
print_tone(struct rtttl_tone tone)
{
        _info("playing %d /100 Hz for %d us",
                        tone.frequency_100hz, tone.duration_us);
}

int
main(int argc, char **argv)
{
        rtttl_play("Jingle Bells:o=5,d=4,b=170,b=170:b,b,b,p,b,b,b,p,b,d6,g.,8a,2b.,8p,c6,c6,c6.,8c6,c6,b,b,8b,8b,b,a,a,b,2a,2d6", print_tone);
        return 0;
}

with the output of

print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 0 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 0 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 117464 /100 Hz for 352941 us
print_tone: playing 78400 /100 Hz for 529410 us
print_tone: playing 88000 /100 Hz for 176470 us
print_tone: playing 98776 /100 Hz for 1058823 us
print_tone: playing 0 /100 Hz for 176470 us
print_tone: playing 104652 /100 Hz for 352941 us
print_tone: playing 104652 /100 Hz for 352941 us
print_tone: playing 104652 /100 Hz for 529410 us
print_tone: playing 104652 /100 Hz for 176470 us
print_tone: playing 104652 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 176470 us
print_tone: playing 98776 /100 Hz for 176470 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 88000 /100 Hz for 352941 us
print_tone: playing 88000 /100 Hz for 352941 us
print_tone: playing 98776 /100 Hz for 352941 us
print_tone: playing 88000 /100 Hz for 705882 us
print_tone: playing 117464 /100 Hz for 705882 us

When instead of print_tone, there is a play_tone procedure with the board-specific code to make the sound, the Jingle Bells song is played.

linguini1
linguini1 previously approved these changes May 11, 2026
Copy link
Copy Markdown
Contributor

@linguini1 linguini1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

lupyuen
lupyuen previously approved these changes May 12, 2026
@lupyuen
Copy link
Copy Markdown
Member

lupyuen commented May 12, 2026

@ghnotgood Please add "Signed-off-by" to your commit. Also add a simple message to the Commit Body, e.g. Add rtttl-c, a simple parsing library, to the audioutils directory. Thanks :-)
https://github.com/apache/nuttx-apps/actions/runs/25669411036/job/75350384159?pr=3477#step:4:84

❌ Missing Signed-off-by
Some checks failed. For contributing guidelines, see:
  https://github.com/apache/nuttx/blob/master/CONTRIBUTING.md

@ghnotgood
Copy link
Copy Markdown
Contributor Author

@lupyuen I am sorry, I forget again. Thank you.

Copy link
Copy Markdown
Contributor

@cederom cederom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @ghnotgood :-)

  • How this solution is differenf from nuttx-apps/examples/audio_rttl [1]? Why do you prefer this particular application?
  • Did you test this solution on a real world hardware? Does it generate tones as intended? Can you please provide testing logs?
  • The code is a tiny C and H file. There is no need to git clone it from external repo. Please add sources directly into the PR. When there is a new release of the upstream we will update it here too. NuttX aims to be self-contained and have least possible amount of external dependencies.

[1] https://github.com/apache/nuttx-apps/tree/275a083464fd08209fd54e7372954977dfd45fbd/examples/audio_rttl

Add a simple library for parsing Ring Tone Text Transfer Language
(RTTTL).

Signed-off-by: Jiri Vlasak <jvlasak@elektroline.cz>
@ghnotgood
Copy link
Copy Markdown
Contributor Author

ghnotgood commented May 13, 2026

@cederom

How this solution is differenf from nuttx-apps/examples/audio_rttl [1]? Why do you prefer this particular application?

The example is an example. I am not sure how to use the example to play a sound I want in my application -- there is no API in header file. Moreover, it looks like cxd56xx-specific example -- I found board_audio_tone_generator procedure in boards/arm/cxd56xx/drivers/audio/cxd56_audio.c file only.

The proposed library, on the other hand, lets a develop define how to make a sound, which may be generic NuttX audio driver or any hacked board-specific solution.

Did you test this solution on a real world hardware? Does it generate tones as intended? Can you please provide testing logs?

Yes, as stated in the Testing section of this PR. The build log is:

$ ./tools/configure.sh -l ../ourboard/configs/
  Copy files
  Select CONFIG_HOST_LINUX=y
  Refreshing...
CP: arch/dummy/Kconfig to /home/myhome/nx/M/arch/dummy/dummy_kconfig
CP: boards/dummy/Kconfig to /home/myhome/nx/M/../ourboard/Kconfig
LN: platform/board to /home/myhome/nx/nuttx-apps/platform/dummy
LN: include/arch to arch/arm/include
LN: include/arch/board to /home/myhome/nx/M/../ourboard/include
LN: drivers/platform to /home/myhome/nx/M/drivers/dummy
LN: include/arch/chip to /home/myhome/nx/M/arch/arm/include/kinetis
LN: arch/arm/src/chip to /home/myhome/nx/M/arch/arm/src/kinetis
LN: arch/arm/src/board to /home/myhome/nx/M/../ourboard/src
mkkconfig in /home/myhome/nx/nuttx-apps/audioutils
mkkconfig in /home/myhome/nx/nuttx-apps/benchmarks
mkkconfig in /home/myhome/nx/nuttx-apps/boot
mkkconfig in /home/myhome/nx/nuttx-apps/canutils
mkkconfig in /home/myhome/nx/nuttx-apps/crypto
mkkconfig in /home/myhome/nx/nuttx-apps/database
mkkconfig in /home/myhome/nx/nuttx-apps/examples/elf/tests
mkkconfig in /home/myhome/nx/nuttx-apps/examples/elf
mkkconfig in /home/myhome/nx/nuttx-apps/examples/mcuboot
mkkconfig in /home/myhome/nx/nuttx-apps/examples/module
mkkconfig in /home/myhome/nx/nuttx-apps/examples/rust
mkkconfig in /home/myhome/nx/nuttx-apps/examples/sotest
mkkconfig in /home/myhome/nx/nuttx-apps/examples
mkkconfig in /home/myhome/nx/nuttx-apps/fsutils
mkkconfig in /home/myhome/nx/nuttx-apps/games
mkkconfig in /home/myhome/nx/nuttx-apps/graphics
mkkconfig in /home/myhome/nx/nuttx-apps/industry/modbus
mkkconfig in /home/myhome/nx/nuttx-apps/industry
mkkconfig in /home/myhome/nx/nuttx-apps/inertial
mkkconfig in /home/myhome/nx/nuttx-apps/interpreters/luamodules
mkkconfig in /home/myhome/nx/nuttx-apps/interpreters
mkkconfig in /home/myhome/nx/nuttx-apps/logging
mkkconfig in /home/myhome/nx/nuttx-apps/lte
mkkconfig in /home/myhome/nx/nuttx-apps/math
mkkconfig in /home/myhome/nx/nuttx-apps/mlearning
mkkconfig in /home/myhome/nx/nuttx-apps/netutils
mkkconfig in /home/myhome/nx/nuttx-apps/sdr
mkkconfig in /home/myhome/nx/nuttx-apps/system
mkkconfig in /home/myhome/nx/nuttx-apps/tee
mkkconfig in /home/myhome/nx/nuttx-apps/testing/arch
mkkconfig in /home/myhome/nx/nuttx-apps/testing/cxx
mkkconfig in /home/myhome/nx/nuttx-apps/testing/drivers
mkkconfig in /home/myhome/nx/nuttx-apps/testing/fs
mkkconfig in /home/myhome/nx/nuttx-apps/testing/libc
mkkconfig in /home/myhome/nx/nuttx-apps/testing/mm
mkkconfig in /home/myhome/nx/nuttx-apps/testing/sched
mkkconfig in /home/myhome/nx/nuttx-apps/testing
mkkconfig in /home/myhome/nx/nuttx-apps/videoutils
mkkconfig in /home/myhome/nx/ourboard-nuttx-tests
mkkconfig in /home/myhome/nx/nuttx-apps/wireless/bluetooth
mkkconfig in /home/myhome/nx/nuttx-apps/wireless/ieee802154
mkkconfig in /home/myhome/nx/nuttx-apps/wireless
mkkconfig in /home/myhome/nx/nuttx-apps
.config:181:warning: override: reassigning to symbol BASE_DEFCONFIG
#
# configuration written to .config
#
$ make
Create version.h
LN: platform/board to /home/myhome/nx/nuttx-apps/platform/dummy
Register: dd
Register: nsh
Register: sh
Register: ping
Register: test_audio
Register: test_eeprom
Register: test_keypad
Register: test_lcd
Register: test_rs485
Register: test_sdcard
CC:  iob/iob_update_pktlen.c iob/iob_update_pktlen.c: In function 'iob_update_pktlen':
iob/iob_update_pktlen.c:128:27: warning: 'penultimate' may be used uninitialized [-Wmaybe-uninitialized]
  128 |       while (next != NULL && nrequire > ninqueue)
      |              ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
iob/iob_update_pktlen.c:52:21: note: 'penultimate' was declared here
   52 |   FAR struct iob_s *penultimate;
      |                     ^~~~~~~~~~~
CC:  chip/kinetis_serial.c chip/kinetis_serial.c: In function 'up_rxint':
chip/kinetis_serial.c:1832:4: warning: #warning "Revisit:  How are errors enabled?" [-Wcpp]
 1832 | #  warning "Revisit:  How are errors enabled?"
      |    ^~~~~~~
CC:  chip/kinetis_sdhc.c In file included from chip/kinetis_sdhc.c:34:
chip/kinetis_sdhc.c: In function 'kinetis_blocksetup':
chip/kinetis_sdhc.c:1906:10: warning: format '%ld' expects argument of type 'long int', but argument 3 has type 'unsigned int' [-Wformat=]
 1906 |   mcinfo("blocksize=%ld, total transfer=%ld (%ld blocks)\n", blocksize,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  ~~~~~~~~~
      |                                                              |
      |                                                              unsigned int
chip/kinetis_sdhc.c:1906:23: note: format string is defined here
 1906 |   mcinfo("blocksize=%ld, total transfer=%ld (%ld blocks)\n", blocksize,
      |                     ~~^
      |                       |
      |                       long int
      |                     %d
chip/kinetis_sdhc.c:1906:10: warning: format '%ld' expects argument of type 'long int', but argument 4 has type 'unsigned int' [-Wformat=]
 1906 |   mcinfo("blocksize=%ld, total transfer=%ld (%ld blocks)\n", blocksize,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1907 |          blocksize * nblocks, nblocks);
      |          ~~~~~~~~~~~~~~~~~~~
      |                    |
      |                    unsigned int
chip/kinetis_sdhc.c:1906:43: note: format string is defined here
 1906 |   mcinfo("blocksize=%ld, total transfer=%ld (%ld blocks)\n", blocksize,
      |                                         ~~^
      |                                           |
      |                                           long int
      |                                         %d
chip/kinetis_sdhc.c:1906:10: warning: format '%ld' expects argument of type 'long int', but argument 5 has type 'unsigned int' [-Wformat=]
 1906 |   mcinfo("blocksize=%ld, total transfer=%ld (%ld blocks)\n", blocksize,
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 1907 |          blocksize * nblocks, nblocks);
      |                               ~~~~~~~
      |                               |
      |                               unsigned int
chip/kinetis_sdhc.c:1906:48: note: format string is defined here
 1906 |   mcinfo("blocksize=%ld, total transfer=%ld (%ld blocks)\n", blocksize,
      |                                              ~~^
      |                                                |
      |                                                long int
      |                                              %d
chip/kinetis_sdhc.c: In function 'kinetis_recvshortcrc':
chip/kinetis_sdhc.c:2235:13: warning: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t' {aka 'long unsigned int'} [-Wformat=]
 2235 |       mcerr("ERROR: Wrong response CMD=%08x\n", cmd);
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  ~~~
      |                                                 |
      |                                                 uint32_t {aka long unsigned int}
chip/kinetis_sdhc.c:2235:43: note: format string is defined here
 2235 |       mcerr("ERROR: Wrong response CMD=%08x\n", cmd);
      |                                        ~~~^
      |                                           |
      |                                           unsigned int
      |                                        %08lx
CC:  main.c main.c: In function 'test_rs485_main':
main.c:43:16: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
   43 |         while (r = read(tty, &ch, 1)) {
      |                ^
CC:  userleds.c In file included from /home/myhome/nx/M/include/debug.h:32,
                 from userleds.c:31:
userleds.c: In function 'board_userled_all':
userleds.c:105:11: warning: format '%X' expects argument of type 'unsigned int', but argument 3 has type 'uint32_t' {aka 'long unsigned int'} [-Wformat=]
  105 |   ledinfo("setting all leds with 0x%08X", ledset);
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  ~~~~~~
      |                                           |
      |                                           uint32_t {aka long unsigned int}
userleds.c:105:39: note: format string is defined here
  105 |   ledinfo("setting all leds with 0x%08X", ledset);
      |                                    ~~~^
      |                                       |
      |                                       unsigned int
      |                                    %08lX
CPP:  /home/myhome/nx/M/../ourboard/scripts/ourboard.ld-> /home/myhome/nx/M/../ourboard/scripts/ourboard.LD: nuttx
Memory region         Used Size  Region Size  %age Used
       vectflash:         444 B         1 KB     43.36%
      cfmprotect:          16 B         16 B    100.00%
       progflash:      223648 B      1022 KB     21.37%
        datasram:       26360 B       128 KB     20.11%
CP: nuttx.hex

Running the test_audio program:

vtk15> test_audio
test_audio_main: rtttl returned 0

The test_audio program contains board-specific code -- I use Kinetis' PIT0 to control the frequency of DAC0 where a speaker is connected. I use PIT1 to control the duration of the sound.

The code is a tiny C and H file. There is no need to git clone it from external repo. [...]

I did it, but now the check fails due to formatting issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants