g | x | w | all
Bytes Lang Time Link
146APLNARS251011T125424ZRosario
04705AB1E251013T081954ZKevin Cr
280Maple251011T193940Zdharr
066Charcoal251010T230514ZNeil
103WhatLang251011T155622ZYufangIG
056Jelly251010T204744ZJonathan
106JavaScript ES7251010T152740ZArnauld

APL(NARS), 146 chars

r←d w;i;l;m;n
i←1⋄r←⍬⋄l←≢w
n←0⋄m←⌊.5+110×2*12÷⍨2+{⍵=2:-∞⋄⍵}'1 2 34 5 6 7d r mf s l tD R MF S L T'⍳i⊃w
n+←1⋄→4×⍳l<i+←1⋄→3×⍳'-'=i⊃w
r,←⊂m n⋄→2×⍳l≥i

// +/14 13 75 28 16=146

The ungolfed version, with line number labels and indentation 4chars for loops

   r←d w;i;l;m;n
1: i←1⋄r←⍬⋄l←≢w
2:     n←0⋄m←⌊.5+110×2*12÷⍨2+{⍵=2:-∞⋄⍵}'1 2 34 5 6 7d r mf s l tD R MF S L T'⍳i⊃w
3:         n+←1⋄→4×⍳l<i+←1⋄→3×⍳'-'=i⊃w
4:     r,←⊂m n⋄→2×⍳l≥i

The input has to be a not void string with chars in '1234567drmfsltDRMFSLT -' the output is a array that has as elements one array of one float and one integer.

The formula for calculate the frequences in Hz of notes from Do3 it seems to be

  h←{⌊.5+110×2*12÷⍨⍵+3}
  h¨0..12
131 139 147 156 165 175 185 196 208 220 233 247 262 
Do  Do# Re  Re# MI  Fa  Fa# Sol Sol#La  La# Si  Do
 0    1  2    3  4   5    6   7    8 9  10  11  12   

Where 0 is the Do3, 1 is Do#3, 2 is Re3 ecc

h would continue to calculate the frequence in herz in both diretion

  Do1  Do2  Do3 Do4  Do5
..-24..-12..0.. 12.. 24..

The note La4 has the number 12+9=21 440Hz

  h 21
440

How you can see here the notes are 12 not 7, but the question want find only the subset of these notes the ones Do Re MI Fa Sol La Si Do, only, 7 notes...

The problem has an easy solution, it is enoght use the formula h above and build the string of search with spaces where are the lost notes as

'1 2 34 5 6 7d r mf s l tD R MF S L T'

These are all corrispondences of notes

  ↑¨d '1234567drmfsltDRMFSLT'
131 147 165 175 196 220 247 262 294 330 349 392 440 494 523 587 659 698 784 880 988 

at '1' there is 131 Hz Do3, at '2' there is 147Hz is Re,..., at 'T' there is 988Hz is Si5

  h 11+12×2 
988

Test:

  d 'ssl-s-D-t-- ssl-s-R-D-- ssS-M-D-t-l-- FFM-D-R-D--'
392 1  392 1  440 2  392 2  523 2  494 3  0 1  392 1  392 1  440 2  392 2  587 2  523 3 
   0 1  392 1  392 1  784 2  659 2  523 2  494 2  440 3  0 1  698 1  698 1  659 2  52
  3 2  587 2  523 3 
  

the note here indicates from "s" has a round value of 392Hz not 391Hz at last seen the table in the wikipedia page on the notes, so above could be ok too.

The function d can make to work with all the 12 notes if the name of missed notes are add example:

'1a2b34c5e6g7dhrimfnsolptDqRuMFvSwLyT'
'1 2 34 5 6 7d r mf s l tD R MF S L T'
'0123456789abcdefghijklmnopqrstuvwxyz'

05AB1E, 47 bytes

v7LJ.•/[&8•Du««ykDdiÌ12*Ì7÷12/o6b*ïX‚ë(ÝyðÊi+])

Attempt it online or verify all test cases. (Minor note, uses ATO instead of TIO, since there used to be an 05AB1E bug with o and TIO is too outdated and therefore still has that bug.)

With extended rules: 88* bytes

v7LJ.•/[&8•Du««yk©di®Ì12*Ì7÷12/o6b*ïX‚ëy'(QiX;Uëy')QiX·Uëy'{Qi¶ëy'}Qi)¶¡`D««`ë¾X‚yðÊi+])

(Assumes {/} won't be nested.)

Try it online. (This one does use TIO instead of ATO with manual +5 bytes workaround for the bug (the Dïs‚à), since ATO times out for some reason..)

Explanation:

Uses a derived formula of the one used by @Neil in his Charcoal answer:

$$f=2^{\frac{1}{12}\left\lfloor\frac{12(n+2)+2}{7}\right\rfloor}\times110 $$

based on the 0-based index \$n\$ in "1234567drmfsltDRMFSLT".

v                      # Loop over the characters `y` of the (implicit) input-string:
 7LJ                   #  Push a list in the range [1,7], and join it to a string
    .•/[&8•            #  Push compressed string "drmfslt"
           Du          #  Push an uppercase copy
             ««        #  Append the three strings together
 yk                    #  Get the (0-based) index of the current character in this,
                       #  or -1 if it's one of the other characters
   D                   #  Duplicate this index
    di                 #  Pop the copy, and if it's NOT -1:
      Ì                #   Increase the index by 2
       12*             #   Multiply by 12
          Ì            #   Increase by 2 again
           7÷          #   Integer-divide by 7
             12/       #   Divide by 12
                o      #   2 to the power this
                 6b*   #   Multiply by 110 (6 as binary)
                    ï  #   Floor it to an integer
      X‚               #   Pair it with a 1
     ë                 #  Else (it's a space or "-"):
      (                #   Negate the -1 to a 1
       Ý               #   Pop and push list [0,1]
        yðÊi           #   If `y` is NOT a space (aka, it's "-"):
            +          #    Add this [0,1] to the values of the top pair instead
]                      # Close the if-statement and loop
 )                     # Wrap all pairs on the stack into a list
                       # (which is output implicitly)
v7LJ.•/[&8•Du««yk      # Same as above
 ©                     #  Store this index in variable `®` (without popping)
  di                   #  Pop and if it's NOT -1:
    ®                  #   Push index `®`
     Ì12*Ì7÷12/o6b*ï   #   Same as above
                    X‚ #   Pair it with the current frequency `X` (1 by default)
   ë                   #  Else (it's one of " -(){}"):
    y'(Qi             '#   If the current character is a "(":
         X;U           #    Push `X`, half it, pop and store it as new `X`
        ëy')Qi        '#   Else-if the current character is a ")":
              X·U      #    Double `X` instead
        ëy'{Qi        '#   Else-if the current character is a "{":
              ¶        #    Push a newline character
        ëy'}Qi        '#   Else-if the current character is a "}":
              )        #    Wrap all pairs on the stack into a list
               ¶¡      #    Split it on the newline character
                 `     #    Pop and push both lists in this pair to the stack
                  D    #    Duplicate the second list
                   ««  #    Merge the three lists of pairs together
                     ` #    Pop and push all pairs separately to the stack again
        ë              #   Else (the current character is "-" or " ")
         ¾X‚           #    Push pair [0,X]
            yðÊi+])    #    Same as above

See this 05AB1E tip of mine (section How to compress strings not part of the dictionary?) to understand why .•/[&8• is "drmfslt".

Maple,  181  179 bytes,  282*  280* bytes

-2 bytes by using @Neil's formula.

Without extensions:

proc(s)S:=seq:g:=table([S("1234567drmfsltDRMFSLT ")]=~[S(floor(110*2^(iquo(12*n+14,7)/12)),n=1..21),0]);w,j:=<[]>,0;S(`if`(i="-",(w[j]+=[0,1]),[(j++),(w(j):=[g[i],1])]),i=s);w end;

Ugolfed:

proc(s)
S:=seq:        # abbreviate seq as S
# next line sets up a table mapping a character to its frequency using @Neil's formula
g:=table([S("1234567drmfsltDRMFSLT ")]=~[S(floor(110*2^(iquo(12*n+14,7)/12)),n=1..21),0]);
w,j:=<[]>,0;   # initialize output Vector w and its size j
for i in s do
if i="-" then
  w[j]+=[0,1]  # if "-" then add 1 to beats of previous note
else
 j++;
 w(j):=[g[i],1]
fi
od;
w;
end;

Inputs string, outputs Vector of [freq,beats]. Golfed version condenses the for loop and if statement into a seq with expression form for if.

Extended version, 280 bytes.

ungolfed;

proc(s)
S:=seq:        # abbreviate seq as S
# next line sets up a table mapping a character to its frequency using @Neil's formula
g:=table([S("1234567drmfsltDRMFSLT ")]=~[S(floor(110*2^(iquo(12*n+14,7)/12)),n=1..21),0]);
w,j,v:=<[]>,0,1;   # initialize output Vector w and its size j and default speed v
for i in s do
if i="-" then
  w[j]+=[0,v]  # if "-" then add v to beats of previous note
elif i="(" then
  v/=2         # double speed
elif i=")" then
  v*=2         # halve speed
elif i="{" then
  k:=j         # record current position
elif i="}" then
  w,=S(w[k+1..]); # repeat
  j+=j-k       # update position
else
 j++;
 w(j):=[g[i],v]
fi
od;
w;
end;

golfed:

proc(s)S:=seq:g:=table([S("1234567drmfsltDRMFSLT ")]=~[S(floor(110*2^(iquo(12*n+14,7)/12)),n=1..21),0]);w,j,v:=<[]>,0,1;S(`if`(i="-",(w[j]+=[0,v]),`if`(i="(",(v/=2),`if`(i=")",(v*=2),`if`(i="{",(k:=j),`if`(i="}",[(w,=S(w[k+1..])),(j+=j-k)],[(j++),(w(j):=[g[i],v])]))))),i=s);w;end;

Note: the beats are output as fractions: 1/2, 3/2 etc. Add one byte to output as floats (initialize v as 1. not 1).

Charcoal, 66 bytes

≔drmfsltηFS≡ι-⊞υE⊟υ⁺κλ ⊞υE²κ⊞υ⟦⌊×¹¹⁰X²∕⁺²÷×¹²∨Σι⁺⁸⌕⁺η↥ηι⁷¦¹²¦¹⟧⭆¹υ

Try it online! Link is to verbose version of code. Explanation: By assigning the values 8..21 to the letters d..T respectively, the following formula gives the exact frequency of the note:

$$ f = 110 \times 2 ^ { \frac 1 {12} \left \lfloor \frac { 12 n + 14 } 7 \right \rfloor } $$

≔drmfsltη

Get the notes C4-B4 in a variable to avoid repetition.

FS≡ι

Switch over the input characters.

-⊞υE⊟υ⁺κλ

For a -, extend the duration of the previous note or rest.

 ⊞υE²κ

For a space, append a length 1 rest.

⊞υ⟦⌊×¹¹⁰X²∕⁺²÷×¹²∨Σι⁺⁸⌕⁺η↥ηι⁷¦¹²¦¹⟧

Otherwise, append a length 1 note of the floor of the frequency as given by the above formula.

⭆¹υ

Pretty-print the final list of notes.

Add 13 bytes to additionally handle ( and ):

≔drmfsltη≔¹ζFS≡ι-⊞υE⊟υ⁺κ∧λζ ⊞υ⟦⁰ζ⟧(≦⊘ζ)≦⊗ζ⊞υ⟦⌊×¹¹⁰X²∕⁺²÷×¹²∨Σι⁺⁸⌕⁺η↥ηι⁷¦¹²ζ⟧⭆¹υ

Attempt This Online! Link is to verbose version of code. (Using ATO to avoid decimals in the output.)

Add 13 bytes to additionally handle { and } (but not nested):

≔drmfsltη≔¹ζFS≡ι-⊞υE⊟υ⁺κ∧λζ ⊞υ⟦⁰ζ⟧(≦⊘ζ)≦⊗ζ{≔Lυε}F✂υε⊞υκ⊞υ⟦⌊×¹¹⁰X²∕⁺²÷×¹²∨Σι⁺⁸⌕⁺η↥ηι⁷¦¹²ζ⟧⭆¹υ

Try it online! Link is to verbose version of code. (This version also includes support for ( and ), but the support for { and } can also be added to the original version.)

Out of interest, I wrote a ZX Spectrum 128K program to translate a basic rpip7 string to a ZX Spectrum 128 PLAY command string. It only works for note lengths of 1-4 due to limitations of the PLAY command.

  10 INPUT LINE a$: REM use LET a$="music goes here" for testing to save retyping each time
  20 LET p$="": LET k=1: LET d=15: LET r=16: LET m=17: LET f=18: LET s=19: LET l=20: LET t=21: REM d..t are the note pitches, k is the current length and p$ is the play command string
  30 FOR i=LEN(a$) TO 1 STEP -1: REM looping backwards to make the length calculation easier
  40 IF a$(i)="-" THEN LET k=k+1: GO TO 90: REM increase the length
  50 IF a$(i)=" " THEN LET p$="3567"(k)+"&"+p$: GO TO 80: REM a rest of the given length
  60 LET n=VAL a$(i)-7*(a$(i)>"_")+1: REM pitch of current note, 2=C3 up to 22=B5
  70 LET p$="O"+STR$ INT ((n+19)/7)+"N"+"3567"(k)+CHR$ (65+n-7*INT (n/7))+p$: REM a note of the right pitch and length
  80 LET k=1: REM reset length
  90 NEXT i
 100 PLAY p$

WhatLang, 103 bytes

[( |.-*)g]match@(len@\0,\_:' ?{"1234567drmfsltDRMFSLT"\in@\_12*7/2+flr@12*2\pow@110*flr@\2>!!}_0\2>)#.

Takes string from the stack as input, outputs the result.

Using the formula: $$\mathrm{frequency} = 2^{\frac1{12}\left\lfloor\frac{12x}7+2\right\rfloor}\times110$$

Try it here!

Jelly, 56 bytes

⁽'ḍBṚÄṾ€;“½⁸VYɼ⁼'»;Œs¤i÷12µ2*×110Ḟ⁸aĖ
‘1¦€0¦;ç¥⁼”-$}?ƒḟ`

A moadic Link that accepts a list of 1234567drmfsltDRMFSLT - characters and yields a list of [length, frequency] pairs.

Try it online!

How?

⁽'ḍBṚÄṾ€;“...»;Œs¤i÷12µ2*×110Ḟ⁸aĖ - Link 1: any, Unused; character, C (never '-')
⁽'ḍBṚ                             - 21928 in binary, reversed -> [0,0,1,0,1,0,1,1,0,1,0,1,0,1]
     Ä                            - cumulative sums -> [0,0,1,1,2,2,3,4,4,5,5,6,6,7]
      Ṿ€                          - unevaluate each -> "00112234455667"
                 ¤                - nilad followed by link(s) as a nilad:
         “...»                    -   dictionary-string = "durum"+"fo"+"salet"
                                                        = "durumfosalet"
               Œs                 - swap-case           = "DURUMFOSALET"
              ;                   - concatenate         = "durumfosaletDURUMFOSALET"
        ;                         - concatenate = "00112234455667durumfosaletDURUMFOSALET"
                  i               - first 1-index of {C} or 0 if not found (if C is a space)
                   ÷12            - divide that by twelve
                      µ           - start a new monadic chain - f(E=that)
                       2*         - two exponentiate {E}
                         ×110Ḟ    - multiply that by 110 and floor
                                    -> frequency or 110 if C is a space
                              ⁸a  - E logical AND {that} -> frequency (0 for a space)
                                Ė - enumerate -> [[1, frequency]]

‘1¦€0¦;ç¥⁼”-$}?ƒḟ` - Main Link: list of characters, Score
                ḟ` - {Score} filter discard itself -> []
               ƒ   - starting with Result = [], reduce {Score} by:
              ?    -   if...
         ⁼”-$}     -   ...condition: {Next} is equal to '-'?
   €0¦             -   ...then: to the rightmost element of {Result}:
‘1¦                -              increment the first element (the length value)
      ;ç¥          -   ...else: concatenate the result of Link 1({Result}, {Next})

The warrior was BṚÄṾ€ going into battle with only durum fo salet (some wheat for a helmet).

JavaScript (ES7), 106 bytes

-5 by using an unfragmented lookup table, as in Neil's answer

s=>s.match(/.-*/g).map(s=>[s<1?0:2**(~~(12*"_1234567drmfsltDRMFSLT".search(s[0])/7+2)/12)*110|0,s.length])

Try it online!


JavaScript (ES7), 111 bytes

-2 thanks to Jonathan Allan

s=>s.match(/.-*/g).map(s=>[(n=" ..1.2.34.5.6.7d.r.mf.s.l.tD.R.MF.S.L.T".search(s[0])/12)&&2**n*110|0,s.length])

Try it online!

Formula

Given \$n\in[3\dots38]\$, the formula for the frequency is:

$$\left\lfloor2^{(n-24)/12}\times 440\right\rfloor$$

Which can be simplified to:

$$\left\lfloor2^{n/12}\times\left(2^{-24/12}\times 440\right)\right\rfloor=\left\lfloor2^{n/12}\times110\right\rfloor$$