Tobb frekvenciabol osszeallo hang generalasa

 ( sza2king | 2017. május 19., péntek - 12:38 )

Hi,

Szeretnek adott hosszusagu (n*10ms) hangmintat eloallitani, amiben tobb (konkretan 6) kuonbozo frekvenciaju (4kHz es 7kHz kozotti) szinusz jel van multiplexelve (kb. mint a DTMF).

Alapvetoen valami librarynak (C, C++, Python) orulnek, ha konnyen kezelheto (meg free es open source), de ha parancssorbol, kesz tool-okkal osszeszkriptelheto (a sox es tarsai latszodnak alkalmasnak) az is megfelelne elso korben.

A kimentet majdnem barmi nem tomoritett lehet, talan legjobb az egyszeru .wav ha file, de az is jo (vagy meg jobb?), ha egy tombben megjelennek a 16bit-es mintak (1 csatorna kell csak, mono).

Google persze dob talalatokat, talan tul sokat is, a keres inkabb azokhoz szol akik csinaltak mar hasonlot.

Erre varnek otleteket.

Koszi,

/sza2

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

A hangminta előállítás sima ügy: össze kell csak adni megfelelő frekvenciájú és amplitúdójú szinusz függvényeket.

Én úgy csinálnám, hogy tetszőleges programnyleven előállítanám a mintákat stdout-ra, és ffmpeg-be pájpolva csinálnék hangfájlt belőle: https://trac.ffmpeg.org/wiki/audio%20types

"DE f32le PCM 32-bit floating-point little-endian"

https://pastebin.com/Yas8Tkqk

Az egyszerűség kedvéért 64 bites lebegőpontos formátumot csináltam inkább: DE f64le PCM 64-bit floating-point little-endian

Ez működik is, kipróbáltam a kommentbe írt parancsokkal: https://pastebin.com/8T9fnLft

A program fordítása és futtatás:

* Lementeni SndGen.java néven
* javac SndGen.java (fordítás, keletkezik egy SndGen.class)
* java SndGen (futtatás - létrejön a /tmp/snd.raw)
* konverzió és lejátszás működik, ahogy a kommentben le van írva.

Koszi, lehet, hogy ezen az uton indulok el, bar lehet, hogy nem Java-ban.

/sza2

Szívesen! Bármi jó, amivel bináris outputot tudsz gyártani. A processzeket összepájpolva akár egyből le is lehet játszani. Illetve ffmpeg van Windowsra is, úgyhogy kis ügyeskedéssel multiplatform is lehet a megoldás.

off

Az a 44 kHz mintavétel hogy jött ki? Tudom, csak egy szám, de szerintem jobban mutatna a 44.1 kHz, mert hardware-ből is annyi leggyakrabban, s akkor nem kell resampling. Vagy 48 kHz.


tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Hasraütés volt, a második, már tesztelt változatban már átírtam 44.1 kHz-re. De a paraméterek finomhangolása úgyis a kérdező feladata, mert ő tudja mit akar vele.

Biztos van jobb és egyszerűbb megoldás, de én egy for ciklussal akárhány milisec-ig mintavételi frekivel számolgatnám a 6 freki pill. értékét, amit a végén előjelesen összeadnék, raw adatként kimentenék és ezt valami konverterrel megetetném ami pl. wav-ot csinálna belőle.

Régebben csináltam hasonlót, akkor a raw adatot eprom-ba írtam és ennek az adatbuszát r/2r hálóval analóggá alakítottam. Az eprom címlábait számlálóval vezéreltem és kész is volt a függvénygenerátor. ;) A kimeneti jel szép volt...

Ügyes :)

Én a ChucK nevű programnyelv-szerűséget használtam, amikor hangot kellett szintetizálnom:

http://chuck.cs.princeton.edu/

A példaprogramok között konkrét DTMF is van, de ami neked kell, az annál is egyszerűbb, tényleg pár sor.

Szerk: annyira azért nem triviális, ő mindenáron a hangkártyát szeretné megszólaltatni, külön rá kell beszélni, hogy fájlba írjon:


// oscillators
[4000, 4523, 5069, 5511, 6112, 6573] @=> int freqs[];
[ .6, .5, .5, .5, .5, .5] @=> float gains[];

SinOsc oscarray[6];
for(0 => int i; i<6; i++) {
oscarray[i] => dac;
freqs[i] => oscarray[i].freq;
gains[i] => oscarray[i].gain;
}

// sound file
me.sourceDir() + "out.wav" => string filename;
if( me.args() ) me.arg(0) => filename;

// pull samples from the dac
dac => Gain g => WvOut w => blackhole;
// this is the output file name
filename => w.wavFilename;

1000::ms => now;

Futtatás:

chuck -s write_sound.ck

A sox rögtön csinál belőle spektrogramot:

sox out.wav -n spectrogram

Erdekes, bar a szintaktikaja nekem kicsit idegen egyelore.

Azert koszi.

/sza2

Ezt egy sima ffmpeg command line-al is elo tudod allitani, az alabbi 440 Hz es 1 kHz egyutt, nyilvan tobb freki ertelemszeruen:

ffmpeg -f lavfi -i "aevalsrc=sin(440*2*PI*t)/10+sin(1000*2*PI*t)/10:d=0.5" out.wav

sox -n -c1 output.wav synth n_szer_0.01 sin freq1_hz sin freq2_hz sin freq3_hz sin freq4_hz sin freq5_hz sin freq6_hz


„Pár marék nerd-et leszámítva kutyát se érdekel már 2016-ban a Linux. Persze, a Schönherz koliban biztos lehet villogni vele, de el kéne fogadni, ez már egy teljesen halott platform. Hagyjuk meg szervergépnek stb…” Aron1988@Proharder Fórum