Sinussvep i Python

Hur funkar tekniken bakom bra hifi?

Moderator: Redaktörer

Användarvisningsbild
JohanS
 
Inlägg: 810
Blev medlem: 2003-10-03
Ort: Uppsala

Sinussvep i Python

Inläggav JohanS » 2006-01-18 23:15

Jag började pyssla lite med programspråket Python häromdagen, försökte mig på att göra ett sinussvep som ska sparas i en fil. Någon slags svep lyckas jag generera, men det låter märkligt. Jag har upplevt samma fenomen tidigare när jag lekt med sinussvep i ett färdigt program, men jag kan inte komma på vad felet var. Ljudfilen finns här: http://user.faktiskt.io/iffe/sample.raw

Koden ser ut såhär:

import math
from struct import *

freqStart, freqEnd = 200, 22000
freq = freqStart
sampleRate = float(44100)
interval = 5
samples = interval * sampleRate
filename = "sample.raw"
stepsize=(freqEnd - freqStart) / samples

file=open(filename, "w")

for sampleIterator in range(samples):
s = pack('<h',int(2**7 * math.sin(freq*(sampleIterator/sampleRate))))
freq=freq+stepsize
file.write(s)

file.close()


Någon som har koll på vad som kan tänkas vara fel?

Användarvisningsbild
Morello
 
Inlägg: 36465
Blev medlem: 2003-05-19
Ort: Stockholm/Täby

Inläggav Morello » 2006-01-19 01:31

Ja, svepet är linjärt. Man använder normalt exponentiella svep."stepsize" måste öka med ökande frekvens.
Driver: www.sybariteaudio.se
-Innehar F-skattsedel-

”Messen ist Wissen, aber messen ohne Wissen ist kein Wissen”

"Es ist noch kein Meister vom Himmel gefallen"

Användarvisningsbild
JohanS
 
Inlägg: 810
Blev medlem: 2003-10-03
Ort: Uppsala

Inläggav JohanS » 2006-01-19 09:43

Japp, tanken var att först göra ett linjärt svep för att se om konceptet (programmeringsmässigt) fungerar överhuvudtaget. Det gör det inte, åtminstone får inte jag det att låta rätt.

Användarvisningsbild
JohanS
 
Inlägg: 810
Blev medlem: 2003-10-03
Ort: Uppsala

Inläggav JohanS » 2006-01-19 13:49

Det funkade fint när jag skickade signalen direkt ut på ljudkortet istället för att spara i en fil. Tack ändå :D

Användarvisningsbild
Svante
Audiot!
 
Inlägg: 37552
Blev medlem: 2004-03-03
Ort: oakustisk

Re: Sinussvep i Python

Inläggav Svante » 2006-01-19 23:10

iffe skrev:
import math
from struct import *

freqStart, freqEnd = 200, 22000
freq = freqStart
sampleRate = float(44100)
interval = 5
samples = interval * sampleRate
filename = "sample.raw"
stepsize=(freqEnd - freqStart) / samples

file=open(filename, "w")

for sampleIterator in range(samples):
s = pack('<h',int(2**7 * math.sin(freq*(sampleIterator/sampleRate))))
freq=freq+stepsize
file.write(s)

file.close()


Någon som har koll på vad som kan tänkas vara fel?

Mja... Nu pratar jag ju inte Python, men jag ser åtminstone två fel, tror jag. Eller tre.

Du multiplicerar med 2^7=32768. Största talet som kan representeras är 32767, det kan alltså bli överstyrton sinusen blr 1. Det är kanske inte hemskt allvarligt, men i en del språk får man "wraparound" om man försöker göra så ock +32768 ersätts med -32768 och det låter inget kul.

Du verkar anta att sin(freq*t) ska ge frekvensen freq. Det gör det inte. Om freq är konstant ger det vinkelfrekvensen freq, dvs frekvensen freq/(2pi). Om freq inte är konstant blir det krångligare. I ditt fall är den proportionell mot t, dvs det står ungefär sin(konstant*t^2). Vad blir resultatet av det då? Jo, allmänt är momentana vinkelfrekvensen för en sinus derivatan av dess argument map tiden. Sug på den en stund.

Om du då har sin(wt) och w=t/k så kommer vinkelfrekvensen att bli derivatan av t^2/k=t*2/k. Det blir en tvåa där som man lätt missar, frekvensen blir dubbelt så stor som man tror.

Hur ska man göra godtyckliga svep då? Jo, man ska ta funktionen för vinkelfrekvens som man vill ha och integrera den map tid och använda den som argument i sinusen.

Alternativt, om det är svårt att räkna ut integralen analytiskt, kan man i stället för varje sampel lägga till ett tal som motsvarar frekvensen just nu. Denna metod är egentligen sämre eftersom den ger en massa additioner och då blir det en massa fel som adderas, och då vet man inte i slutänden riktigt vilket fasläge sinusen har.

Sen lät filen skunk, men det beror på att den är upphackad i bitar på nåt sätt. Det måste bero på nåt Pythonspecifikt som jag inte begriper.[/i]
Så länge har jag längat efter att loudness war skulle vara över. Nu börjar jag tro att vi faktiskt är där. Kruxet är att vi förlorade.

Användarvisningsbild
JohanS
 
Inlägg: 810
Blev medlem: 2003-10-03
Ort: Uppsala

Re: Sinussvep i Python

Inläggav JohanS » 2006-01-20 11:05

Svante skrev:Du multiplicerar med 2^7=32768. Största talet som kan representeras är 32767, det kan alltså bli överstyrton sinusen blr 1. Det är kanske inte hemskt allvarligt, men i en del språk får man "wraparound" om man försöker göra så ock +32768 ersätts med -32768 och det låter inget kul.


Jag hittade ett färdigt program (i C) som gjorde svep, och där drog de ifrån 1.0 efter funktionen. Här har vi alltså svaret på varför.

Svante skrev:Du verkar anta att sin(freq*t) ska ge frekvensen freq. Det gör det inte. Om freq är konstant ger det vinkelfrekvensen freq, dvs frekvensen freq/(2pi). Om freq inte är konstant blir det krångligare. I ditt fall är den proportionell mot t, dvs det står ungefär sin(konstant*t^2). Vad blir resultatet av det då? Jo, allmänt är momentana vinkelfrekvensen för en sinus derivatan av dess argument map tiden. Sug på den en stund.

Om du då har sin(wt) och w=t/k så kommer vinkelfrekvensen att bli derivatan av t^2/k=t*2/k. Det blir en tvåa där som man lätt missar, frekvensen blir dubbelt så stor som man tror.


Ja, det var en liten tankevurpa från min sida. Fick sätta mig ner med papper och penna och fundera lite, tack för ett utförligt svar.

Svante skrev:Hur ska man göra godtyckliga svep då? Jo, man ska ta funktionen för vinkelfrekvens som man vill ha och integrera den map tid och använda den som argument i sinusen.

Alternativt, om det är svårt att räkna ut integralen analytiskt, kan man i stället för varje sampel lägga till ett tal som motsvarar frekvensen just nu. Denna metod är egentligen sämre eftersom den ger en massa additioner och då blir det en massa fel som adderas, och då vet man inte i slutänden riktigt vilket fasläge sinusen har.

Sen lät filen skunk, men det beror på att den är upphackad i bitar på nåt sätt. Det måste bero på nåt Pythonspecifikt som jag inte begriper.


Mycket nyttig information, jag har försökt hitta lite på nätet men det var inte det lättaste. Problemet med att filen låter upphackad löste jag genom att inte spara undan i en fil alls, det är ju till ljudkortet den ska skickas ändå. Då lät det bra.


Återgå till Teknikforum


Vilka är online

Användare som besöker denna kategori: lemmts och 19 gäster