Posted by Navid Zamani on Sun 28th Oct 00:34
download | new post | report as spam

  1. #!/bin/bash
  2. # music.sh
  3.  
  4. # MUSIC WITH JUST BASH
  5. #                By: Navid Zamani <navidD0TzamaniATgooglemailD0Tcom>
  6. #       Inspired by: The small example from TLDP.
  7. #      Last updated: 2012-10-27
  8. # NoLicense License: You are not allowed to use this, unless you agree that
  9. #                    there is no such thing as "intellectual property", there never was, and there never will be.
  10.  
  11. # WARNING:
  12. #   In this example, we’re using aplay instead of /dev/dsp, to get 48kHz stereo output, which improves things greatly.
  13. #   To get 100% pure, change $sps to 8000, uncomment the lines marked "PURE" and comment the ones marked "UNPURE".
  14.  
  15. # All samples are in U8 (unsigned byte).
  16.  
  17. # Which device to use for PURE playback. (The PCM format must match *exactly*, and the device must not be in use.)
  18. sndDevice="/dev/dsp"
  19. #sndDevice="/dev/snd/pcmC0D00p"
  20.  
  21. # Samples per second.
  22. sps=48000 # UNPURE
  23. #sps=8000 # PURE
  24.  
  25. # Audio channels
  26. channels=2 # UNPURE
  27. #channels=1 # PURE
  28.  
  29. function mknote() { # Note synthesis in pure bash!
  30.   # Parametes
  31.   bpm="$1" # beats per minute
  32.   note="$2" # note in Hz (A4 = 440Hz)
  33.   laenge="$3" # Note length (1 = 1/1, 2 = 1/2, …)
  34.   # Calculation of duration
  35.   dauer=$(( ( (sps*60)/bpm )/laenge ))
  36.   schwingung=$(( sps / note ))
  37.   # Sawtooth synthesis
  38.   # Warning: Stereo = Two bytes per sample!
  39.   eval "echo -n \$'$(
  40.     for (( t=0; t < dauer; t++ ))
  41.       do for (( c=0; c < channels; c++ ))
  42.            do s=$(( t % schwingung ))
  43.               [[ $s -eq 0 ]] && echo -n '\x80' || printf '\\x%02X' $s
  44.            done
  45.       done
  46.   )'"
  47. }
  48.  
  49. function mknoteC() { # Cached version
  50.   file="sawtooth-${2}Hz-${1}BPM-${3}th.${sps}Hz-${channels}ch-U8.pcm"
  51.   [ -e "$file" ] || mknote $1 $2 $3 > "$file"
  52.   echo "$(<"$file")"
  53. }
  54.  
  55. # For this song...
  56. bpm=60
  57.  
  58. # That way we have everything needed, when we change the melody.
  59. echo "Rendering ($bpm BPM, $sps Hz): "
  60.  
  61. l=2; echo -n "    Half notes: "
  62. c52=$( mknoteC $bpm 523 $l ); echo -n C5-
  63. b42=$( mknoteC $bpm 494 $l ); echo -n B4-
  64. ais42=$( mknoteC $bpm 466 $l ); echo -n Ais4-
  65. a42=$( mknoteC $bpm 440 $l ); echo -n A4-
  66. gis42=$( mknoteC $bpm 415 $l ); echo -n Gis4-
  67. g42=$( mknoteC $bpm 392 $l ); echo -n G4-
  68. fis42=$( mknoteC $bpm 370 $l ); echo -n Fis4-
  69. f42=$( mknoteC $bpm 349 $l ); echo -n F4-
  70. e42=$( mknoteC $bpm 330 $l ); echo -n E4-
  71. dis42=$( mknoteC $bpm 311 $l ); echo -n Dis4-
  72. d42=$( mknoteC $bpm 296 $l ); echo -n D4-
  73. cis42=$( mknoteC $bpm 277 $l ); echo -n Cis4-
  74. c42=$( mknoteC $bpm 262 $l ); echo -n C4-
  75. b32=$( mknoteC $bpm 247 $l ); echo -n B3-
  76. ais32=$( mknoteC $bpm 233 $l ); echo -n Ais3-
  77. a32=$( mknoteC $bpm 220 $l ); echo -n A3-
  78. gis32=$( mknoteC $bpm 208 $l ); echo -n Gis3-
  79. g32=$( mknoteC $bpm 196 $l ); echo -n G3-
  80. fis32=$( mknoteC $bpm 185 $l ); echo -n Fis3-
  81. f32=$( mknoteC $bpm 175 $l ); echo -n F3-
  82. e32=$( mknoteC $bpm 165 $l ); echo -n E3-
  83. dis32=$( mknoteC $bpm 156 $l ); echo -n Dis3-
  84. d32=$( mknoteC $bpm 147 $l ); echo -n D3-
  85. cis32=$( mknoteC $bpm 139 $l ); echo -n Cis3-
  86. c32=$( mknoteC $bpm 131 $l ); echo -n C3-
  87. n2=$( mknoteC $bpm $sps $l ); echo N
  88.  
  89. l=4; echo -n " Quarter notes: "
  90. c5=$( mknoteC $bpm 523 $l ); echo -n C5-
  91. b4=$( mknoteC $bpm 494 $l ); echo -n B4-
  92. ais4=$( mknoteC $bpm 466 $l ); echo -n Ais4-
  93. a4=$( mknoteC $bpm 440 $l ); echo -n A4-
  94. gis4=$( mknoteC $bpm 415 $l ); echo -n Gis4-
  95. g4=$( mknoteC $bpm 392 $l ); echo -n G4-
  96. fis4=$( mknoteC $bpm 370 $l ); echo -n Fis4-
  97. f4=$( mknoteC $bpm 349 $l ); echo -n F4-
  98. e4=$( mknoteC $bpm 330 $l ); echo -n E4-
  99. dis4=$( mknoteC $bpm 311 $l ); echo -n Dis4-
  100. d4=$( mknoteC $bpm 296 $l ); echo -n D4-
  101. cis4=$( mknoteC $bpm 277 $l ); echo -n Cis4-
  102. c4=$( mknoteC $bpm 262 $l ); echo -n C4-
  103. b3=$( mknoteC $bpm 247 $l ); echo -n B3-
  104. ais3=$( mknoteC $bpm 233 $l ); echo -n Ais3-
  105. a3=$( mknoteC $bpm 220 $l ); echo -n A3-
  106. gis3=$( mknoteC $bpm 208 $l ); echo -n Gis3-
  107. g3=$( mknoteC $bpm 196 $l ); echo -n G3-
  108. fis3=$( mknoteC $bpm 185 $l ); echo -n Fis3-
  109. f3=$( mknoteC $bpm 175 $l ); echo -n F3-
  110. e3=$( mknoteC $bpm 165 $l ); echo -n E3-
  111. dis3=$( mknoteC $bpm 156 $l ); echo -n Dis3-
  112. d3=$( mknoteC $bpm 147 $l ); echo -n D3-
  113. cis3=$( mknoteC $bpm 139 $l ); echo -n Cis3-
  114. c3=$( mknoteC $bpm 131 $l ); echo -n C3-
  115. n=$( mknoteC $bpm $sps $l ); echo N
  116.  
  117. l=8; echo -n "  Eighth notes: "
  118. c58=$( mknoteC $bpm 523 $l ); echo -n C5-
  119. b48=$( mknoteC $bpm 494 $l ); echo -n B4-
  120. ais48=$( mknoteC $bpm 466 $l ); echo -n Ais4-
  121. a48=$( mknoteC $bpm 440 $l ); echo -n A4-
  122. gis48=$( mknoteC $bpm 415 $l ); echo -n Gis4-
  123. g48=$( mknoteC $bpm 392 $l ); echo -n G4-
  124. fis48=$( mknoteC $bpm 370 $l ); echo -n Fis4-
  125. f48=$( mknoteC $bpm 349 $l ); echo -n F4-
  126. e48=$( mknoteC $bpm 330 $l ); echo -n E4-
  127. dis48=$( mknoteC $bpm 311 $l ); echo -n Dis4-
  128. d48=$( mknoteC $bpm 296 $l ); echo -n D4-
  129. cis48=$( mknoteC $bpm 277 $l ); echo -n Cis4-
  130. c48=$( mknoteC $bpm 262 $l ); echo -n C4-
  131. b38=$( mknoteC $bpm 247 $l ); echo -n B3-
  132. ais38=$( mknoteC $bpm 233 $l ); echo -n Ais3-
  133. a38=$( mknoteC $bpm 220 $l ); echo -n A3-
  134. gis38=$( mknoteC $bpm 208 $l ); echo -n Gis3-
  135. g38=$( mknoteC $bpm 196 $l ); echo -n G3-
  136. fis38=$( mknoteC $bpm 185 $l ); echo -n Fis3-
  137. f38=$( mknoteC $bpm 175 $l ); echo -n F3-
  138. e38=$( mknoteC $bpm 165 $l ); echo -n E3-
  139. dis38=$( mknoteC $bpm 156 $l ); echo -n Dis3-
  140. d38=$( mknoteC $bpm 147 $l ); echo -n D3-
  141. cis38=$( mknoteC $bpm 139 $l ); echo -n Cis3-
  142. c38=$( mknoteC $bpm 131 $l ); echo -n C3-
  143. n8=$( mknoteC $bpm $sps $l ); echo N
  144.  
  145. # Demo melody (60 BPM), showing different note and pause lengths, and a simple appregiato.
  146. melody1="$g38$n8$e48$n8$d48$c48$d48$c48$d48$n8$c48$n8$a38$n8$g38$n8$n$g3$f3$n$g3$e4$d4$c4$c4$b3$c4$cis4$n$cis4$d4$n$g38$g48$e48$e38$d48$c48$d48$c48$d48$d38$c48$c38$a38$a48$g38$g48$n$g3$f3$n$g3$a3$d4$c4$b3$a3$b3$c42"
  147.  
  148. # Play it!
  149.  
  150. #echo -n "$melody1" > "melody1.${sps}Hz-${channels}ch-U8.pcm" # Output to file?
  151. aplay -t raw -c "$channels" -f U8 -r $sps <( echo -n "$melody1" ) # UNPURE
  152. #echo -n "$melody1" > "$sndDevice" # PURE

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily
.
Syntax highlighting:

To highlight particular lines, prefix each line with @@
   Remember me