<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=23&amp;t=14156&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2016-01-11T18:21:04+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=23&amp;t=14156&amp;mode</id>
<entry>
<author><name><![CDATA[rekon]]></name></author>
<updated>2016-01-11T18:21:04+01:00</updated>
<published>2016-01-11T18:21:04+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=14156&amp;p=150272#p150272</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=14156&amp;p=150272#p150272"/>
<title type="html"><![CDATA[Generator sygnałów]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=14156&amp;p=150272#p150272"><![CDATA[
Czesc<br />robiłem projekt na studia i tak mi przyszło do głowy że może ewentualnie ktoś mógłby chcieć go wykorzystać do czegokolwiek <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br />Zadanie postawione przede mną to było zrobić generator prostych sygnałów taki DDS ale na bardzo ograniczonym paśmie częstotliwości - podstawowe założenie było conajmniej od 0 do 20kHz. Miałem wykorzystać do tego atmegę oraz jakiś przetwornik DAC ale koncepcja musiała być zmieniona. Zamiast tego jako małą platformę potraktowano komputer Raspberry Pi, z wykorzystaniem najbardziej optymalnego języka jakim jest Python3 <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br />Ostatecznie program generuje sygnały spróbkowane do 192kHz, więc szału nie ma ale z jakiegoś niezrozumiałego dla mnie powodu wszystkie znalezione przeze mnie generatory tego typu mają próbkowanie 44,1kHz.<br />No i ponieważ to jest pythonowe ustrojstwo działa na każdym komputerze na którym jest zainstalowany Python3 (pod pythonem 2 też powinno ruszyć).<br />Wiem że na tym forum rzadko pojawiają się skrypty pythonowe ale cóż <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> może komuś się przyda.<br /><br />[syntax=python]# -*- coding: utf-8 -*-<br />import wave<br />from math import sin, pi, copysign<br />from array import array<br />import platform<br />import os<br /><br />SAMPLING_FREQ = 192000<br />MAX_FREQ = 80000<br />MIN_FREQ = 10<br />MAX_AMLP = 127<br />MIN_AMLP = 1<br />MAX_TIME = 60<br />MIN_TIME = 1<br /><br /><br />def play_sig(freq, time, ampl, sign_type):<br />    &quot;&quot;&quot;<br />    :param freq:<br />    :param time:<br />    :param ampl:<br />    :param sign_type:<br />    :return:<br />    &quot;&quot;&quot;<br />    # check input values #<br />    if freq &gt; MAX_FREQ:<br />        freq = MAX_FREQ<br />    elif freq &lt; MIN_FREQ:<br />        freq = MIN_FREQ<br />    if ampl &gt; MAX_AMLP:<br />        ampl = MAX_AMLP<br />    elif ampl &lt; MIN_AMLP:<br />        ampl = MIN_AMLP<br />    if time &lt; MIN_TIME:<br />        time = MIN_TIME<br />    elif time &gt; MAX_TIME:<br />        time = MAX_TIME<br /><br />    # check what signal type to produce #<br />    if sign_type == 's':<br />        function = sine<br />    elif sign_type == 't':<br />        function = triangle<br />    elif sign_type == 'z':<br />        function = sawtooth<br />    elif sign_type == 'p':<br />        function = square<br />    else:<br />        raise RuntimeError(&quot;You have to enter one char from \'s\', \'p\', \'t\', \'z\' &quot;<br />                           &quot;in order to specify what type of signal you want to hear&quot;)<br /><br />    # calculate samples for one period of signal #<br />    signal = array('h')  # switch to l and it will be 32 bits - remember to also change setsampwidth to 4<br />    ratio = SAMPLING_FREQ / float(freq)  # float added to be compatible with python 2<br />    cycle = SAMPLING_FREQ<br />    min_phase = 1 / ratio<br />    for i in range(SAMPLING_FREQ):<br />        phase = (i / ratio) % 1  # get only part after decimal point<br />        if phase &lt; min_phase / 10 and i != 0:<br />            cycle = i<br />            break<br />        value = function(phase, ampl)<br />        signal.append(value)<br />    # extend signal by cycling it #<br />    signal *= int(time * SAMPLING_FREQ / cycle)<br /><br />    # create wave file and enter parameters #<br />    output = wave.open('temp.wav', 'w')<br />    output.setnchannels(1)  # mono sound<br />    output.setsampwidth(2)  # 16 bit resolution<br />    output.setframerate(SAMPLING_FREQ)<br />    output.writeframes(signal)<br />    output.close()<br /><br />    # play newly created wave file<br />    play('temp.wav')<br /><br /><br />def triangle(phase, ampl):<br />    return int((abs(phase - 0.5) - 0.25) * 4 * ampl * 256)<br /><br /><br />def sine(phase, ampl):<br />    return int((sin(phase * 2 * pi)) * ampl * 256)<br /><br /><br />def sawtooth(phase, ampl):<br />    return int((phase - 0.5) * 2 * ampl * 256)<br /><br /><br />def square(phase, ampl):<br />    return int(copysign(ampl * 256, phase - 0.5))  # phase &lt; 0.5 ? -ampl*256 , ampl*256<br /><br /><br />def play(filename):<br />    if platform.system() == 'Windows':<br />        os.system('start ' + filename)<br />    else:<br />        os.system('aplay ' + filename + ' -Dplug:default')[/syntax]<br /><br />Jeśli z jakiegoś powodu ktoś chciałby to ulepszać to proponuje aby dla sinusa postarać się o przesunięcie w fazie o 1/4 okresu tak aby nieciągłości związane z zapętlaniem jednego cyklu trafiały na miejsce gdzie sinus ma najmniejsze pochylenie a nie tam gdzie pochylenie jest największe. Prawdopodobnie wystarczy w funkcji sine przy wyliczaniu odpowiedniej wartości zrobić (phase-0.25) zamiast phase samo z siebie, ale trzeba by było to jeszcze sprawdzić, albo po prostu zastosować w funkcji sine kosinusa <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=7932">rekon</a> — 11 sty 2016, o 18:21</p><hr />
]]></content>
</entry>
</feed>