Morse Nowy Rok

33

To jest Tygodniowe Wyzwanie nr 1. Temat: Przetwarzanie audio

Twoim zadaniem jest napisanie programu, który zapisuje plik audio do płyty (w formacie do wyboru), który zawiera kod Morse'a za 2015, tj

..--- ----- .---- .....

Możesz wybrać dowolny rodzaj dźwięku dla segmentów, np. Falę sinusoidalną o pojedynczej częstotliwości, akord, szum, jakiś instrument (np. Używając plików MIDI), o ile jest to słyszalne. Istnieją jednak pewne ograniczenia dotyczące czasu:

  • Krótkie odcinki muszą mieć co najmniej 0,2 sekundy długości.
  • Długie odcinki muszą być co najmniej 3 razy dłuższe niż krótkie odcinki.
  • Przerwy między segmentami w obrębie cyfry powinny być tej samej długości co krótkie segmenty.
  • Przerwy między cyframi powinny mieć taką samą długość jak długie segmenty.
  • Każdy segment i przerwa mogą różnić się do 10% od średniej długości tego rodzaju segmentu / przerwy.
  • Cały plik audio nie może być dłuższy niż 30 sekund.

Przerwy nie muszą być całkowicie ciche, ale segmenty Morse'a powinny być słyszalnie głośniejsze niż przerwy.

Należy pamiętać, że mają napisać plik audio. Nie można po prostu odtwarzać dźwięku, np. Za pomocą sygnałów systemowych. Możesz używać dowolnego rodzaju biblioteki do obsługi formatu pliku i generowania dźwięku, ale nie możesz używać wbudowanych funkcji do kodowania Morse'a.

To jest kod golfowy, więc wygrywa najkrótsza odpowiedź (w bajtach).

Proszę rozważyć połączenie z przesłaniem wynikowego pliku audio (na SoundCloud lub podobnym), aby ludzie mogli sprawdzić wynik bez konieczności uruchamiania kodu. Jeśli przesyłasz do SoundCloud, pamiętaj, aby włączyć pobieranie na karcie Uprawnienia ścieżki.

Jeśli dane wyjściowe używają raczej nietypowego formatu pliku, dodaj informacje o tym, jak je odtworzyć i / lub przekonwertować na bardziej popularny format i przesłać.

Przykładowy utwór

Jest to ręcznie wygenerowana przykładowa ścieżka, która jest zgodna ze specyfikacją i wykorzystuje szum dla segmentów Morse'a (a konkretnie szum tła mikrofonu). Oto link do SoundCloud, jeśli wbudowany odtwarzacz nie działa dla Ciebie.

Szczegóły nagrody

Przyznam nagrodę za najkrótsze zgłoszenie w języku programowania audio , tj. Języku zaprojektowanym do syntezy dźwięku. Ta lista nie jest kompletna, więc możesz użyć innego języka programowania audio, jeśli go znasz. Jeśli nie masz pewności, czy jakiś język, którego chcesz używać, klasyfikuje się jako język programowania audio, daj mi znać w komentarzach lub na czacie , a my możemy to omówić.

Pamiętaj, że Twoje zgłoszenie musi być zgodne ze wszystkimi zasadami - w szczególności musi napisać plik, co może nie być możliwe we wszystkich językach programowania audio. Na przykład, o ile wiem, gibber może odtwarzać tylko dźwięk i nie zapisywać go w pliku.

Martin Ender
źródło
1
Dodatkowe wyzwanie: Spraw, aby brzmiało naprawdę ładnie.
Kaz Wolfe
6
@Mew Jak fajnie może brzmieć Morse?
Martin Ender
1
Wykonanie tego w Brainf ** k sprawiłoby, że byłoby to niesamowite na tak wielu poziomach bonusowych.
Maszt
@Mast Prawdopodobnie, ale niestety BF nie może zapisać do pliku. ;) (Postaram się być bardziej wyrozumiały przy tym następnym razem.)
Martin Ender
Czy formaty zapisu muzyki, które zawierają tylko partyturę i nie zawierają dźwięku (.mid, .abc pokazano poniżej), są uważane za dopuszczalne jako „plik audio”? Co z formatami „trackera”, które zawierają zarówno próbki, jak i partyturę, ale nie mają renderowanej ścieżki audio (.mod, .xm)?
Tobia,

Odpowiedzi:

4

AWK BASH: 66 86 67 74 bajtów

Zgodnie z prośbą Martina Büttnera dodałem tempo, odkąd sprawdziłem standard Notacji ABC wydaje się, że nie ma zdefiniowanej wartości domyślnej (dziękuję nutki za wskazanie tego).
Piszę również w pliku dyskowym (a) zamiast STDOUT, ponieważ pytanie wyraźnie chciało „plik na dysku”.

a=C3z;echo "X:1
K:A
Q:99
CzCz$a$a$a3$a$a$a$a${a}3Cz$a$a$a${a}3CzCzCzCzC">a

Ustawiam tempo 99, co powoduje, że plik audio trwa 22 sekundy; Jest wolniejszy niż moja poprzednia wersja, ale przynajmniej teraz powinien mieć taką samą długość na każdym odtwarzaczu ABC i zmieści się poniżej 30 sekund.

Wygląda ... bardzo podobnie do poprzedniej wersji, jak widać: Ostatnia (mam nadzieję: o)) wersja wyniku 2015

Tutaj jest nowy plik midi .

Pierwsza wersja BASH (brakuje tempa)

Dlaczego nie pomyślałem o tym po raz pierwszy ...: o)

To o 22 bajty mniej niż w AWK, dla tego samego wyniku

a=C3z;echo "X:1
K:A
CzCz$a$a$a3$a$a$a$a${a}3Cz$a$a$a${a}3CzCzCzCzC"

Podobnie jak poprzednia wersja w AWK, zapisuje na standardowym pliku notacji „ABC” (dzięki Tobia za to, że stwierdzenie „L” było opcjonalne)

To wygląda tak: ostatnia wersja partycji „2015”

I brzmi dokładnie tak jak poprzednia wersja .

Poprzednia wersja w AWK (86 bajtów)

Oto nowa wersja; trochę dłużej, ale z bardziej dokładnym czasem. Pozwoliłem pierwszej wersji poniżej na porównanie / odniesienie:

BEGIN{a="C3z";print"X:1\nK:A\nL:1/8\nCzCz"a a a"3"a a a a a"3Cz"a a a a"3CzCzCzCzCz";}

Jest to nadal prawidłowy plik „abc”, który wygląda następująco: wynik w 2015 r

Oto nowy plik midi (przyspieszyłem tempo, aby pozostać poniżej limitu 30 sekund).

Pierwsza wersja w AWK (66 bajtów):

Jest to o wiele mniej interesujące niż moja poprzednia odpowiedź , ale jest o wiele krótsze, więc:

BEGIN{print"X:1\nK:A\nL:1/4\nCCC2C2C2zC2C2C2C2C2zCC2C2C2C2zCCCCC"}

Wyprowadza to prawidłowy plik „abc”, który można wczytać (między innymi) EasyABC. Będzie to wyglądać tak: Wynik „2015” w morse

i zabrzmi to tak (plik midi) . +

LeFauve
źródło
Powinieneś opublikować go jako ABC bez opakowania AWK i odebrać nagrodę!
Tobia,
Tobia, ABC to format pliku, a nie język programowania. I jak dotąd z 86 bajtami jest to najkrótsza odpowiedź ... Pytanie brzmi teraz: „czy wynikowy dźwięk jest wystarczająco bliski wymaganiom, aby odpowiedź była ważna?”
LeFauve,
Nazwałbym to także formatem pliku, ale strona wiki, do której prowadzi OP, wymienia go jako język programowania dźwięku. Wprowadziłem własny plik ABC jako wpis, wraz z bardziej odpowiednim programem Csound. Zobaczmy, co o tym myślą.
Tobia,
Taki jest problem z wiki ... czasami ludzie, którzy je edytują, popełniają błędy: o). Wiele różnych rzeczy można nazwać „językami programowania”, ale myślę, że ABC nie jest jedną z nich. W każdym razie dzięki za odkrycie „L” było opcjonalne. Zaoszczędziło mi to kilka bajtów; o)
LeFauve
„Długie segmenty muszą być co najmniej 3 razy dłuższe niż krótkie segmenty”. Ostatnia pokazana linia muzyczna nie spełnia wymagań.
mbomb007
13

kod maszynowy x86 (plik .COM): 121 120 113 109 bajtów

Hexdump:

00000000  b4 3e bb 01 00 cd 21 b4  3c 31 c9 ba 3e 01 cd 21  |.>....!.<1..>..!|
00000010  4a b4 09 cd 21 be 56 01  8a 0c 46 e8 0c 00 b1 32  |J...!.V...F....2|
00000020  e8 07 00 81 fe 6d 01 75  ef c3 88 cb c0 e3 07 c1  |.....m.u........|
00000030  e1 04 30 d2 b4 02 00 da  cd 21 e2 fa c3 2e 73 6e  |..0......!....sn|
00000040  64 00 00 00 18 ff ff ff  ff 00 00 00 02 00 00 10  |d...............|
00000050  00 00 00 00 01 24 33 33  99 99 99 66 99 99 99 99  |.....$33...f....|
00000060  99 66 33 99 99 99 99 66  33 33 33 33 33           |.f3....f33333|
0000006d

Można go łatwo uruchomić pod DosBox; dane wyjściowe to plik .SND o nazwie SND. Oto wersja wyjściowa FLAC (a tutaj plik .COM).

Skomentowany montaż:

    org 100h

start:
    ; close stdout
    mov ah,3eh
    mov bx,1
    int 21h
    ; open snd
    mov ah,3ch
    xor cx,cx
    mov dx,filename
    int 21h
    ; write the header
    ; we used the `snd` part of the header as file name, back off one byte
    dec dx
    mov ah,9h
    int 21h
    mov si,data
.l:
    ; data read cycle
    ; read the current byte in cl (zero-extending to 16-bit)
    ; notice that ch is already zero (at the first iteration it's 0 from the
    ; int 21h/3ch, then we are coming from gen, which leaves cx to zero)
    mov cl,[si]
    ; move to next byte
    inc si
    ; generate the tone
    call gen
    ; generate the pause
    mov cl,50
    call gen
    ; repeat until we reach the end of data
    cmp si,eof
    jne .l
    ; quit
    ret

gen:
    ; generate a sawtooth wave at sampling frequency/2 Hz
    ; receives length (in samples>>4) in cx, with lowest bit indicating if
    ; it has to write a wave or a pause
    mov bl,cl
    ; shift the rightmost bit all the way to the left; this kills the
    ; unrelated data and puts a 128 in bl (if cx & 1 != 0)
    shl bl,7
    ; rescale the samples number
    shl cx,4
    ; zero the starting signal
    xor dl,dl
    ; prepare the stuff for int 21h
    mov ah,2h
.l:
    ; increment the signal
    add dl,bl
    ; write it
    int 21h
    ; decrement iteration count and loop
    loop .l
    ret

    ; .SND file header (4096 samples, mono, PCM)
header:
    db "."
    ; we also use "snd" as the file name
filename:
    db "snd",0,0,0,24,0xff,0xff,0xff,0xff,0,0,0,2,0,0,0x10,0,0,0,0,1
    ; terminator for int 21h/ah=9h
    db '$'
data:
    ; generated by gendata.py
    incbin "data.dat"
eof:

The data.datZawiera powyżej jest łatwy w obsłudze przedstawia ciąg Morse'a (niższy nieco: dźwięk / dźwięk, górne 7 bitów Długość dźwięku w próbkach >> 4) generowane przez skrypt Pythonie

#!/usr/bin/env python2
import sys

# source string
s = "..--- ----- .---- ....."
# samples
sr = 4096
conv =  {
            '.': 1 | (((sr/5) >> 4) & ~1),    # dot:   1/5 second, dI/dt=1
            '-': 1 | (((sr/5*3) >> 4) & ~1),  # line:  3/5 second, dI/dt=1
            ' ':     ((sr/5*2) >> 4) & ~1     # space: 2/5 second (+1/5 from the always-present pause), dI/dt=0 (silent)
        }
sys.stdout.write(''.join(chr(conv[a]) for a in s))
Matteo Italia
źródło
Nie musisz koniecznie mieć rozszerzenia pliku, jeśli pozwoli ci to zaoszczędzić cztery bajty.
Martin Ender
4
@ MartinBüttner: w rzeczywistości pozwala mi zaoszczędzić 3 bajty. aOd a.sndkładzie się tuż przed nagłówku SND, która rozpoczyna się .sndpo bajtem zerowym, więc otrzymuję .sndudział za darmo i recyklingu jego zero-terminator. Ponadto fakt, że nagłówek zaczyna się o jeden bajt po nazwie pliku, pozwala mi użyć a inc dxdo przejścia do nagłówka (1 bajt) zamiast mov dx, header(3 bajty). OTOH, gdybym mógł nazwać to .sndsam, mógłbym zaoszczędzić dwa bajty, ale nie jestem pewien, czy prawdziwy DOS na to pozwoli (traktowanie rozszerzenia pod DOS było dość osobliwe).
Matteo Italia
Z wywołaniem pliku zrobiłem kilka testów .SND: dostałem się .SNDna DosBox, SND~1na FreeDOS i oczekuję czegoś innego na „prawdziwym” DOS; dlatego jest to zdecydowanie obszar „niezdefiniowanego zachowania”. W końcu zdecydowałem się na wywołanie pliku SND(1 bajt mniej z powodu usuniętego a, zachowując koszt inc dx- który staje się dec dx).
Matteo Italia,
8

Mathematica - 130

r = Riffle;
s = SoundNote;
Export["m.mid", 
 Sound@
   r[Flatten@
     r[
       s[0,.4(Boole@#+.5)]&/@Array[#>4&,5,5-#]&/@{2,0,1,5},
       (b=None~s~#&)@.6
     ],[email protected]
   ]
]

Graj online

śmigać
źródło
Och, możesz także użyć notacji infix dla Export, na przykład "m.mid"~Export~Sound@....
Martin Ender
(b=None~s~#&)@.6powinno być (b=None~s~#&)@.4 również, możesz zapisać 3 znaki używającr = Riffle; s = SoundNote; Export["m.mid", Sound@r[r[Table[s[0, If[{1, 2, 11}~MemberQ~k || k > 15, .2, .6]], {k, 20}], None~s~.2], None~s~.4, 11]]
DavidC
Martin, ale w każdej przerwie było już .2. .4 + .2
DavidC
@DavidCarraher Ah, masz rację.
Martin Ender
7

Perl 5: 94 122 140

Pliki SND mają prostsze nagłówki, nie trzeba drukować w formacie binarnym. Te wersje produkują monofoniczny plik SND 8 kHz o nazwie „a”:

open A,'>a';print
A".snd",pack"N*",24,-1,2,8e3,1,map{(--$|x3)x(894261072>>$_&1?1600:400)}0..39

W rezultacie plik .

Stare rozwiązanie. Tworzy 8-bitowy plik WAV mono 1kHz o nazwie „a”:

open
A,'>a';print
A pack"A4lA8lssllssA4ls*",RIFF,17040,WAVEfmt,16,1,1,(1e3)x2,1,8,data,17004,map{($_)x(894261072>>$v++&1?400:100)}(255,0)x20

W rezultacie plik .

Aby uzyskać 122 znaki, musiałem wkleić nagłówek w formacie binarnym zamiast go pakować, co utrudnia skopiowanie kodu. Wersja ucieczkowa to:

open
A,'>a';print
A"RIFF\x90B\0\0WAVEfmt \0\0\0\0\0\xe8\0\0\xe8\0\0\0\0datalB\0\0",pack"s*",map{($_)x(894261072>>$v++&1?400:100)}(255,0)x20

Kodowanie Base64 rzeczywistego rozwiązania 122 bajtów:

b3BlbgpBLCc+YSc7cHJpbnQKQSJSSUZGkEIAAFdBVkVmbXQgEAAAAAEAAQDoAwAA6AMAAAEACABk
YXRhbEIAACIscGFjayJzKiIsbWFweygkXyl4KDg5NDI2MTA3Mj4+JHYrKyYxPzQwMDoxMDApfSgy
NTUsMCl4MjA=
nutki
źródło
Może mógłbyś użyć .aurozszerzenia. Dobra robota!
F. Hauri
7

AWK: 172 170 bajtów

... i bez korzystania z biblioteki wave! (*)

BEGIN{for(;++i<204;){d=d"\177\177\n";D=D"\n\n"}t=d d d D;d=d D;T=D D D;u=t t t;print".snd\0\0\0\30\0\0\221\306\0\0\0\2\0\0\20\0\0\0\0\1"d d u T u t t T d u t T d d d d d}

Powoduje to wyjście pliku audio Sun au na standardowe wyjście, które może być odtwarzane przez VLC (między innymi). Chociaż format pliku au nie ma żadnych ograniczeń częstotliwości próbkowania, VLC odmawia odtworzenia dowolnego pliku o częstotliwości próbkowania gorszej niż 4096 Hz, więc użyłem tej częstotliwości

EDYCJA: Link do wynikowego pliku audio w DropBox


(*) Czy nie powinna być za to premia? ; o)

LeFauve
źródło
Nie potrzebujesz miejsca w d=d "\177... konkatenacji. To oszczędza bajt. Ale kiedy odtwarzam wynikowy plik audio, wygląda na to, że brakuje mu ostatniego dit 5.
Mark Reed
Dzięki. Za pomocą tej samej sztuczki zapisałem drugi bajt z inną konkatenacją. Właśnie sprawdziłem plik audio w wersji VLC 2.1.1 i brzmi on kompletnie. Z jakiego gracza korzystałeś?
LeFauve,
Korzystałem z QuickTime Player na OS X. Otworzyłem go w VLC i brzmi dobrze, więc nieważne. Wina Apple'a, nie twoja.
Mark Reed
7

Python, 155

Używa wbudowanego modułu falowego Pythona.

import wave
n=wave.open(*"nw")
k=17837
n.setparams((2,2,k,0,"NONE",0))
h=k*1314709609
while h:[n.writeframes(`i%9`)for i in[0]*(2-h%2)*k+range(h%4*k)];h/=4

Zapisuje do pliku o nazwie n .

Dziękuję Sp3000 za sugestie dotyczące korzystania ze zrozumienia listy dla pętli (pomogło to usunąć nieco wcięcia).

Posłuchaj tego:

https://soundcloud.com/bitpwner/morse-the-new-year-2015

Oto link do SoundCloud, jeśli wbudowany odtwarzacz nie działa dla Ciebie.

Skomentowany kod:

import wave
n=wave.open("n.wav","w")         # Open a wav file for writing
k=44100                            
n.setparams((2,2,k,0,"NONE","")) # Sets the minimal params for the wav file
w=n.writeframes
h=23450475295733                 # Contains base-4 morse: '.'=1, '-'=3, ' '=0
while h:
    for i in range(h%2*k):w(h%4*chr(i%99)) # Writes saw-tooth signal using i%99
    w((2-h%2)*k*" ")                       # Writes the pauses
    h/=4
Vectorized
źródło
Ponieważ wjest to efekt uboczny, myślę, że możesz wymienić comp, aby zaoszczędzić dwa bajty:while h:[w(h%4*chr(i%99))for i in range(h%2*k)];w((2-h%2)*k*" ");h/=4
Sp3000
@ Sp3000 oo ... nie myślałem o tym = D. dzięki!
Vectorized
To może być głupie pytanie, ale jeśli h jest dzielone przez 4 dla każdej iteracji, jak zatrzymuje się pętla while?
Derek 朕 會 功夫
@Derek 朕 會 功夫 W przypadku Pythona, gdy h staje się 0, przyjmuje wartość False, kończąc pętlę. Pętla while to sztuczka golfowa polegająca na wydobywaniu wartości w sekwencji „11333033333013333011111” jeden po drugim.
Vectorized
@bitpwner Rozumiem, że 0 oznacza fałsz, ale czy nie jest tak, że dla wszystkich liczb dodatnich, jeśli podzielisz go przez inną liczbę dodatnią, nie ma możliwości, aby uzyskać 0?
Derek 朕 會 功夫
6

C #, 556 552 536 535 516 506 503 491 483 bajtów

Korzysta z biblioteki Wav.Net .

using System;using System.Linq;namespace WavDotNet.Core{using S=Samples<float>;class P{static void Main(){var w=new WavFileWrite<float>("a",9999);var b=new Tools.Generators.Sawtooth(9999);Func<long,float,S>g=(t,a)=>b.Generate32Bit(new TimeSpan(t),99,a);var l=2500000;S x=g(l,1),y=g(l*3,1),z=g(l*3,0),_=g(l,0),v=new S(new[]{x,_,x,_,y,_,y,_,y,z,y,_,y,_,y,_,y,_,y,z,x,_,y,_,y,_,y,_,y,z,x,_,x,_,x,_,x,_,x}.SelectMany(c=>c).ToList());w.AudioData.Add(new Channel<float>(v,0));w.Flush();}}}

Dane wyjściowe do pliku o nazwie a.

Wynik hostowany na Dropbox

Nieskluczony kod:

using System;
using System.Linq;
namespace WavDotNet.Core
{
    using FloatSamples = Samples<float>;
    class P
    {
        static void Main()
        {
            var file = new WavFileWrite<float>("output.wav", 9999);
            var sawtoothGen = new Tools.Generators.Sawtooth(9999);
            Func<long, float, FloatSamples> generate = (t, amplitude) => sawtoothGen.Generate32Bit(new TimeSpan(t), 99, amplitude);
            var length = 2500000;
            FloatSamples shortBeep = generate(length, 1),
            longBeep = generate(length * 3, 1),
            shortPause = generate(length * 3, 0),
            longPause = generate(length, 0),
            allSamples = new FloatSamples(new[] { shortBeep, longPause, shortBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, shortPause,
                longBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, shortPause, 
                shortBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, shortPause, 
                shortBeep, longPause, shortBeep, longPause, shortBeep, longPause, shortBeep, longPause, shortBeep }
                .SelectMany(c => c).ToList());
            file.AudioData.Add(new Channel<float>(allSamples, 0)); // 0 == ChannelPositions.Mono
            file.Flush();
        }
    }
}
ProgramFOX
źródło
5

Pyton 3) 2, 191 188 174 171 (bez bibliotek)

Pliki WAV są niezwykle proste. Chciałem wypróbować bez bibliotek. Z jakiegoś powodu moje pliki powodują awarię Windows Media Player. Szybki czasPracebłędy w połowie pliku. Rozwiązuje to konwersja na większą częstotliwość próbkowania za pomocą Audition.

Aktualizacja : Wdrożono kilka optymalizacji z odpowiedzi Perla. Teraz wyświetla tylko nazwę ni próbkowanie 1000 Hz. Edytowane informacje powyżej odpowiednio.

w,s=200*" ",50*"~~  "
a,b,c=s+w,3*s+w,2*w
open(*"nw").write("RIFF\xD46\0\0WAVEfmt \20\0\0\0\1\0\1\0\xE8\3\0\0\xE8\3\0\0\1\0\10\0data\xB06\0\0"+a*2+b*3+c+b*5+c+a+b*4+c+a*5)

Stara wersja

w,s=1600*" ",200*"~~~~    "
a,b,c=s+w,3*s+w,2*w
open("n.wav","wb").write("RIFF\244\265\1\0WAVEfmt \20\0\0\0\1\0\1\0@\x1f\0\0@\x1f\0\0\1\0\10\0data\200\265\1\0"+a*2+b*3+c+b*5+c+a+b*4+c+a*5)
PurkkaKoodari
źródło
4

C # ~ 485 bajtów

Korzystanie z biblioteki Wav.Net .

using WavDotNet.Core;namespace System.Collections.Generic{using f=Single;class T{static void Main(){var i=new WavFileWrite<f>("x",8000);Func<long,Samples<f>>g=d=>new WavDotNet.Tools.Generators.Sawtooth(8000).Generate32Bit(new TimeSpan(d),600,1);var s=new List<f>();var k="..--- ----- .---- .....";foreach(var c in k){s.AddRange(c=='.'?g(2000000):g(6000000));s.AddRange(new f[1600]);if(c==' '){s.AddRange(new f[3200]);}}i.AudioData.Add(new Channel<f>(new Samples<f>(s),0));i.Flush();}}}

A oto wynik.

Wersja do odczytu,

using WavDotNet.Core;

namespace System.Collections.Generic
{
    using f = Single;

    class T
    {
        static void Main()
        {
            var i = new WavFileWrite<f>("x", 8000);
            Func<long, Samples<f>> g = d => new WavDotNet.Tools.Generators.Sawtooth(8000).Generate32Bit(new TimeSpan(d), 600, 1);
            var s = new List<f>();
            var k = "..--- ----- .---- .....";

            foreach (var c in k)
            {
                s.AddRange(c == '.' ? g(2000000) : g(6000000));
                s.AddRange(new f[1600]);

                if (c == ' ')
                {
                    s.AddRange(new f[3200]);
                }
            }

            i.AudioData.Add(new Channel<f>(new Samples<f>(s), 0));
            i.Flush();
        }
    }
}
Sam
źródło
Możesz zaoszczędzić niektóre bajty, zawijając klasę w przestrzeni nazw System.Collections.Generic (która faktycznie działa). Istnieje również kilka niepotrzebnych białych znaków, które można usunąć.
ProgramFOX
4

C # 382 333 bajtów

Nie używa żadnych niestandardowych bibliotek, zapisuje wav 8bits na próbkę 44100 próbek na sekundę wav, z czym mam nadzieję, że jest to prawidłowy nagłówek (wydaje się, że gra / ładuje się szczęśliwie w WMP / .NET / Audacity).

Nagłówek jest kodowany w standardzie base64, a Morse jest kodowany jako sygnał wł / wył, który jest przechowywany w jednym długim (64 bity), ponieważ ostatnie 5 bitów jest takich samych jak pierwszy.

Wynik można znaleźć tutaj

Kod do gry w golfa:

using System.IO;class P{static void Main(){using(var w=new FileStream("w.wav",FileMode.Create)){int i=0,d=9980;w.Write(System.Convert.FromBase64String("UklGRhCCCgBXQVZFZm10IBAAAAABAAEARKwAAESsAAABAAgAZGF0YeyBCgA="),0,44);for(var k=5899114207271221109L;i++<d*69;w.WriteByte((byte)(System.Math.Sin((k>>(i/d)%64&1)*i*0.1)*127+127)));}}}

Z komentarzami:

using System.IO;

class P
{
    static void Main()
    {
        using(var w=new FileStream("w.wav",FileMode.Create))
        {
            int i=0,d=9980; // d is samples per tone

            // write wav header
            w.Write(System.Convert.FromBase64String("UklGRhCCCgBXQVZFZm10IBAAAAABAAEARKwAAESsAAABAAgAZGF0YeyBCgA="),0,44);

            for(var k=5899114207271221109L; // 0101000111011101110111010001110111011101110111000111011101110101 as long
                i++<d*69; // 69 is number of bits
                w.WriteByte((byte)(
                    System.Math.Sin(
                        (k>>(i/d)%64&1) // read bit (0 or 1)
                        *i*0.1) // mul by ticker (sin(0) = 0)
                    *127+127)) // make sensible
            );
        }
    }
}
VisualMelon
źródło
Wyzwanie nie wymaga nazwy pliku do końca .wav, więc możesz zapisać tam 4 bajty.
ProgramFOX
Fajny sposób dopasowania 69-bitowego kodu PWM do 64-bitowej stałej. Próbowałem czegoś takiego, ale prawdopodobnie nie mogłem skrócić mojego kodu za pomocą twojej metody.
nutki
2

SuperCollider , 625 605 bajtów

Zgłoszenie języka programowania audio!

Dane wyjściowe są zapisywane w pliku bw formacie AIFF. Windows Media Player nie otwiera się, ale działa dobrze w odtwarzaczu VLC Media Player. Wygenerowany plik ato plik OSC .

c=0;d=0;f={c=c+d;d=0.2;[c,[\s_new,\w,1001,0,0,\freq,800]]};g={c=c+d;d=0.2;[c,[\n_free,1001]]};h={c=c+d;d=0.6;[c,[\s_new,\w,1001,0,0,\freq,800]]};i={c=c+d;d=0.6;[c,[\n_free,1001]]};x=[f.value,g.value,f.value,g.value,h.value,g.value,h.value,g.value,h.value,i.value,h.value,g.value,h.value,g.value,h.value,g.value,h.value,g.value,h.value,i.value,f.value,g.value,h.value,g.value,h.value,g.value,h.value,g.value,h.value,i.value,f.value,g.value,f.value,g.value,f.value,g.value,f.value,g.value,f.value,i.value];Score.recordNRT(x,"morse.osc","Morse2015.aiff");SynthDef("w",{arg freq=440;Out.ar(0,SinOsc.ar(freq,0,0.2))}).writeDefFile;

Stworzyłem kilka funkcji SuperCollider: fgeneruje krótki sygnał dźwiękowy, gkrótką przerwę, hdługi sygnał dźwiękowy i idługą przerwę. SuperCollider potrzebuje pozycji początkowych dla każdej fali sinusoidalnej, a nie długości, więc musiałem stworzyć funkcje generujące falę z prawidłową pozycją początkową i muszę wywoływać funkcje za każdym razem, gdy potrzebuję fali sinusoidalnej. (Nie mogłem przechowywać fali o określonej długości w zmiennej do ponownego użycia). The\wDefinicja jest tworzona na końcu bloku kodu.

Na moim komputerze z systemem Windows nie zapisał pliku audio w tym samym katalogu co mój kod, ale w tym katalogu:

C:\Users\MyName\AppData\Local\VirtualStore\Program Files (x86)\SuperCollider-3.6.6

Wynik hostowany na Dropbox

Kod z wcięciem:

c = 0;
d = 0;
f = { c=c+d;d=0.2;[ c, [ \s_new, \w, 1001, 0, 0,  \freq, 800 ] ] };
g = { c=c+d;d=0.2; [ c, [\n_free, 1001]] };
h = { c=c+d;d=0.6; [ c, [ \s_new, \w, 1001, 0, 0, \freq, 800]]};
i = { c=c+d;d=0.6;[ c, [\n_free, 1001]] };

x = [ f.value, g.value, f.value, g.value, h.value, g.value, h.value, g.value, h.value, i.value,
      h.value, g.value, h.value, g.value, h.value, g.value, h.value, g.value, h.value, i.value,
      f.value, g.value, h.value, g.value, h.value, g.value, h.value, g.value, h.value, i.value,
    f.value, g.value, f.value, g.value, f.value, g.value, f.value, g.value, f.value, i.value
];

Score.recordNRT(x, "morse.osc", "Morse2015.aiff");

SynthDef("w",{ arg freq = 440;
    Out.ar(0,
         SinOsc.ar(freq, 0, 0.2)
    )
}).writeDefFile;
ProgramFOX
źródło
2

ChucK - 1195 217 201 147 145 144

ChucK to język programowania audio. bitpwner pomógł mi obniżyć to z 201 bajtów do 147 bajtów.

SinOsc s;WvOut w=>blackhole;"y"=>w.wavFilename;int j;for(1016835=>int i;i>0;2/=>i){s=>w;j++;(i%2?200:600)::ms=>now;s=<w;(j%5?200:600)::ms=>now;}

Oto bezpośredni link do SoundCloud, jeśli wbudowany odtwarzacz nie działa dla Ciebie.

KSFT
źródło
1
Udało mi się obniżyć do 164 za pomocą podobnej sztuczki zastosowanej w mojej odpowiedzi:WvOut w=>blackhole;"x"=>w.wavFilename;SinOsc s=>w;0=>int j;for(1016835=>int i;i>0;2/=>i){j++;300=>s.freq;(600-i%2*400)::ms=>now;s=<w;(j%5>0?200:600)::ms=>now;s=>w;}
Vectorized
@bitpwner Używasz, jaby ominąć tablicę?
KSFT
Liczby 1016835binarne to 11111000010000000011. jma po prostu śledzić przerwy między poszczególnymi cyframi 2015(każda cyfra ma 5 dźwięków).
Vectorized
@bitpwner Ah, nawet tego nie zauważyłem. To naprawdę fajny pomysł!
KSFT,
Możesz edytować go w swojej odpowiedzi, aby mieć większą szansę na nagrodę. imo, poprawa nie jest wiele, aby uzasadnić nową odpowiedź, ponieważ już wykonałeś większość pracy nad rozpracowaniem Chucka;)
Vectorized
2

Csound, 140 + 40 = 180

Język programowania audio.

To jest plik orkiestry:

instr 1
a1 oscil 2^15,990,1
out a1
endin

a to jest plik wyniku:

f1 0 512 10 1
t0 300
i1 0 1
i1 2
i1 40
i1 60
i1 62
i1 64
i1 66
i1 68
i1 4 3
i1 8
i1 12
i1 18
i1 22
i1 26
i1 30
i1 34
i1 42
i1 46
i1 50
i1 54

Rozmiary są obliczane przy założeniu, że nie ma dodatkowych białych znaków, terminatora jednowierszowego (UNIX) i żadnego terminatora po ostatniej linii.

Wywołujesz je za pomocą polecenia csound:

csound morse.org morse.sco

który utworzy plik wyjściowy w bieżącym katalogu, domyślnie o nazwie „test.aif”

https://soundcloud.com/whatfireflies/morse-code-golf-in-csound/s-qzsaq

Mógłbym ogolić dwa lub trzy bajty, wybierając brzydszy kształt fali, ale podoba mi się dźwięk tradycyjnej fali sinusoidalnej Morse'a.

PS: Jestem całkowitym nowicjuszem w Csound, wszelkie wskazówki dotyczące gry w golfa są mile widziane, szczególnie jeśli chodzi o plik z wynikami!

Tobia
źródło
Ach, nie mogłem się doczekać CSound. Gdyby nikt nie opublikował odpowiedzi, prawdopodobnie spróbowałbym napisać jedną z nich. :)
Martin Ender
1

pieprzenie mózgu , 649 bajtów

++[>-[+>++[++<]>]>[>..........-..........+<-]-[+>++[++<]>]>[....................-]<<<<<-]+++[>+++[>-[+>++[++<]>]>[>..........-..........+<-]<<<-]-[+>++[++<]>]>[....................-]<<<-]-[+>++[++<]>]>[....................-]+++++[>-[+>++[++<]>]>[....................-]+++[>-[+>++[++<]>]>[>..........-..........+<-]<<<-]<<<-]+++[>-[+>++[++<]>]>[....................-]<<<-]-[+>++[++<]>]>[>..........-..........+<-]++++[>-[+>++[++<]>]>[....................-]+++[>-[+>++[++<]>]>[>..........-..........+<-]<<<-]<<<-]++[>-[+>++[++<]>]>[....................-]<<<-]+++++[>-[+>++[++<]>]>[....................-]-[+>++[++<]>]>[>..........-..........+<-]<<<<<-]

Generuje to sekwencję 8-bitowych próbek bez znaku, które można odtwarzać z prędkością 8000 próbek na sekundę za pomocą narzędzia takiego jak aplayLinux. Kredyt do tabeli stałych BF .

Wypróbuj online!

Nieco mniej golfa

DIT DIT DAH DAH DAH
++[>
 -[+>++[++<]>]>[>..........-..........+<-]
 -[+>++[++<]>]>[....................-]
<<<<<-]
+++[>
 +++[>
  -[+>++[++<]>]>[>..........-..........+<-]
 <<<-]
 -[+>++[++<]>]>[....................-]
<<<-]
-[+>++[++<]>]>[....................-]
DAH DAH DAH DAH DAH
+++++[>
 -[+>++[++<]>]>[....................-]
 +++[>
  -[+>++[++<]>]>[>..........-..........+<-]
 <<<-]
<<<-]
+++[>
 -[+>++[++<]>]>[....................-]
<<<-]
DIT DAH DAH DAH DAH
-[+>++[++<]>]>[>..........-..........+<-]
++++[>
 -[+>++[++<]>]>[....................-]
 +++[>
  -[+>++[++<]>]>[>..........-..........+<-]
 <<<-]
<<<-]
++[>
 -[+>++[++<]>]>[....................-]
<<<-]
DIT DIT DIT DIT DIT
+++++[>
 -[+>++[++<]>]>[....................-]
 -[+>++[++<]>]>[>..........-..........+<-]
<<<<<-]
sufitowy
źródło