Audio en Python

Moderators: jkien, Xilvo

Gebruikersavatar
Berichten: 7.463

Re: Audio en Python

Ik weet nog niet of ik verder met Python ga werken. Dat ligt eraan hoe gemakkelijk of ongemakkelijk dat gaat. Als ik een gemaakt geluid niet direct kan afspelen zonder dat eerst als een geluidsbestandje te exporteren vind ik dat in elk geval al een groot bezwaar. Er zijn ook alternatieven zoals SuperCollider en Nyquist die meer specifiek op audio en signaalbewerking gericht zijn, en die ik ook nog wil uitproberen.

Gebruikersavatar
Berichten: 1.605

Re: Audio en Python

Wellicht vind je het leuk verder te studeren. Ik was niet tevreden met de aangedragen oplossing. Je blijkt niet erg gemotiveerd in de opties welke ik aanreikte.

Met de minst mogelijke tools heb ik een voorbeeldje gemaakt hoe men leuk geluiden kunt creëren met audio algoritmen. Hiermee kun je de essentiële dingen van geluid bewerking zelf onderzoeken.

Mijn voorbeeld:
Als input een exponentieel afnemende sinus. Als response/echo een Impulse Response of First Order System (gemoduleerd met verschillende frequenties). Als output de convolutie input met impulse responce. btw. de impulse responce word genomen het signaal is discreet met een samplerate.

Ik heb een methode uitgezocht wat vermoedelijk ook in jouw situatie zou werken. Anders moet je een beetje debuggen of mij vragen. En gebaseerd op de interactieve pyplot's.

De mp3 word gegenereerd en opgeslagen. En zou je dan kunnen openen op betreffende locatie: persoonlijke folder of vergelijkbaar in Linux. De naam: 'my_first_audio.mp3'.

Ik heb een knopje play toegevoegd en zou de standaard player moeten openen van de OS. Of dit gaat werken bij jouw weet ik niet. Volgens mijn onderzoek moet je dan de onderstaande regels: windows (uit) en linux (in) commenteren. Echter dien je de speler steeds te sluiten alvorens een nieuw geluid te creëren (kleine routine aanleren).

Wellicht kun je ook bibliotheken downloaden met -pip. Dan kan je meer geavanceerd afspeel/play functies oproepen (echter integratie in een volledige GUI is moeilijker).

Echter het bewerken van signalen blijft vergelijkbaar met numpy en scipy enzo.

Code: Selecteer alles

# windows
os.system("my_first_audio.mp3")

# linux
#os.system("mpg123 " + "my_first_audio.mp3")
Input: Pure sinus met exponentiële decay:
$$s_{in}=\exp(-\text{d} \cdot t/2) \sin(2 \cdot \pi \cdot \text{pitch} \cdot t)$$

Responce: Impulse gemoduleerd met random frequenties (de echo van ruimte):
$$r=\exp(-\text{e} \cdot t/2) \left( \sin(2 \cdot \pi \cdot f_1 \cdot t) + \sin(2 \cdot \pi \cdot f_2 \cdot t)+ \cdots \right) $$

Output: De convolutie van input en responce:
$$s_{out}=s_{in}*r$$

Onderstaand de code. Ik heb veel commentaar dat je de weg zult vinden. Hopelijk stimuleert dit jouw verder te studeren.

Code: Selecteer alles

#Open pyplot in separate interactive window
from IPython import get_ipython
get_ipython().run_line_magic('matplotlib', 'qt5')

import os
from random import randrange
import numpy as np
from scipy.io.wavfile import write
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

# Maak 4 grafieken aan
fig, ax = plt.subplots(4,figsize=(8, 10))
plt.subplots_adjust(top=0.95,bottom=0.05,left=0.1,right=0.95,hspace=0.5,wspace=0.1)

# Laatste grafiek niet plotten (plaats maken voor widgets: knoppen en sliders)
ax[3].axis("off")

# Maak slider toon lengte
time = plt.axes([0.25, 0.2,0.4, 0.02])
s_time = Slider(time, 'tijduur noot [seconden]:', 1, 10, valinit=3)

# Maak slider grondtoon
pitch = plt.axes([0.25, 0.175,0.4, 0.02])
s_pitch = Slider(pitch, 'toonhoogte [Hz]:', 0, 5000, valinit=440, valstep = 1)

# Maak slider harmonics
harmonics= plt.axes([0.25, 0.15,0.4, 0.02])
s_decay = Slider(harmonics, 'decay [seconden]:', 0,10, valinit=5)


# Maak slider response tijd
responce= plt.axes([0.25, 0.1,0.4, 0.02])
s_responce = Slider(responce, 'echo decay [seconden]: ', 0.001,5, valinit=0.001)

# Maak knot afspelen gecreerde ttom
play = plt.axes([0.75, 0.1, 0.1, 0.075])
b_play = Button(play, 'Play')

# Definieer samplerate:
rate=10000
geluid=[]

def createmp3(signal, samplerate):
   
    # Geschaalde versie van data (tbv. normalisering)
    scaled = np.int16(signal/np.max(np.abs(signal)) * 32767)
    
    # Wegschrijven van scaled in .mp3 of .wav
    write('my_first_audio.mp3',samplerate,scaled)  
    
    
def mp3play(file):

    # Native player on operating system
    #https://pythonbasics.org/python-play-sound/

    # windows
    os.system("my_first_audio.mp3")

    # linux
    #os.system("mpg123 " + "my_first_audio.mp3")

def updateplot(val):
    
    # Lees waarden van sliders in integers
    time=s_time.val
    pitch=s_pitch.val
    decay=s_decay.val
    responce=s_responce.val

    # Maak plotjes leeg
    ax[0].clear()
    ax[1].clear()   
    ax[2].clear()    

    ######################################
    #####Creer sinus net harmonischen#####
    ######################################
    
    # Creer tijd schaal gebaseerd op samplerate
    #time=int(time*pitch)
    t=np.linspace(0,time,int(rate*time))
    
    # Creer grondtoon sinus met frequentie pitch:
    data=np.sin(t*np.pi*pitch*2)    
    
    # Input sinus met exponentiele decay
    data=np.exp(-t*decay*0.5)*data
    
    # Plot Input
    ax[0].set_title("Input: Decayed Sine Wave")
    ax[0].plot(t,data)
   

    ######################################
    ##### Impusle Responce (envelop) #####
    ######################################
    
    # Plot impulse responce signaal
    impulse=np.exp(-t/responce)
     
    ######################################
    ### Moduleer Impulse rand freq.   ####
    ######################################

    #Creer random ruimte met resonantie frequenties    
    random=randrange(5000)
    echo=np.sin(t*np.pi*random*2)

    for i in range(20):
        random=randrange(5000)
        echo=echo+1/20*np.sin(t*np.pi*random*2)  
 
    echo=impulse*echo
    ax[1].set_title("Echo Ruimte: Decayed Random Frequenties.")
    ax[1].plot(t,echo)        
        
    
    ######################################
    ##### Convolutie en Signaal      #####
    ######################################   
    
    #Bepaal dubbele tijdschaal door convolutue    
    tijd=np.linspace(0,2*time,-1+int(rate*2*time))
    
    #Bereken de convolutie
    signaal=np.convolve(echo,data,mode="full")
    
    #Plot Grafiek geconvuleerd signaal
    
    ax[2].set_title("Output: Geconvoleerd met echo.")    
    ax[2].plot(tijd,signaal)  
    
    #Creer Wave bestand
    createmp3(signaal,rate)
    
    
# Weergave grafieken eerste keer doorlopen code.
updateplot(1)

# Update grafieken na wijzigen sliders.
s_time.on_changed(updateplot);
s_pitch.on_changed(updateplot);
s_decay.on_changed(updateplot);
s_responce.on_changed(updateplot);

#Knop afspelen mp3 via operating systeem
b_play.on_clicked(mp3play)
Convolutie Audio.png

Gebruikersavatar
Berichten: 7.463

Re: Audio en Python

Dank voor het vele werk. Ik heb je programma net geprobeerd maar op mijn computer werkt het niet (lege grafieken, geen geluid en geen geluidsbestandje). Aangezien ik als alternatief ook nog SuperCollider heb ben ik daar nu ook mee in de weer geweest, en daarmee kan ik op mijn computer (na de nodige strubbelingen) nu wel direct geluiden/muziekjes maken. Dus lijkt het mij handiger om daarmee verder te gaan.

Gebruikersavatar
Berichten: 1.605

Re: Audio en Python

Mogelijk is hetzelfde probleem dat de versie van mathplotlib de oudere versie is.

Dat zelfde issue was toen ook bij de Jacobi. Wil je weten waarom? Of liever geen Python meer voor jouw?

Gebruikersavatar
Berichten: 1.605

Re: Audio en Python

Verander dit eens:
Bovenste regel als comment met #.
En "plt.tight_layout()" toevoegen.

Volgens mij heb jij mathplotlib versie 2.4 als ik goed herinner.

Code: Selecteer alles

#plt.subplots_adjust(top=0.95,bottom=0.05,left=0.1,right=0.95,hspace=0.5,wspace=0.1)
plt.tight_layout()
Laatst gewijzigd door OOOVincentOOO op zo 21 nov 2021, 18:26, 1 keer totaal gewijzigd.

Gebruikersavatar
Berichten: 7.463

Re: Audio en Python

Python ging heel goed voor de simulaties die we toen gemaakt hebben, vandaar dat ik het ook eens voor audio wilde uitproberen. Maar aangezien SuperCollider specifiek op audio gericht is en nu ook op mijn computer al goed werkt hou ik het maar liever daarbij. Computeren is op zich ook niet mijn hobby, ik gebruik het enkel maar als ik het ergens specifiek voor nodig heb.

Gebruikersavatar
Berichten: 7.463

Re: Audio en Python

Ik heb nu dit:
dit.png

Ik zie in je programma wel dit:

Code: Selecteer alles

# Maak 4 grafieken aan
fig, ax = plt.subplots(4,figsize=(8, 10))
plt.subplots_adjust(top=0.95,bottom=0.05,left=0.1,right=0.95,hspace=0.5,wspace=0.1)

Gebruikersavatar
Berichten: 7.463

Re: Audio en Python

Zo zien de grafieken er bij mij uit:
fig1.png

Gebruikersavatar
Berichten: 1.605

Re: Audio en Python

Zonder enige meer informatie?

Heb je deze regel uitgeschakeld met een "#":

Code: Selecteer alles

#plt.subplots_adjust(top=0.95,bottom=0.05,left=0.1,right=0.95,hspace=0.5,wspace=0.1)
Vervangen door:

Code: Selecteer alles

plt.tight_layout()
EDIT:
Makkelijker probeer deze versie eens:

Code: Selecteer alles

#V1.01
#Open pyplot in separate interactive window
from IPython import get_ipython
get_ipython().run_line_magic('matplotlib', 'qt5')

import os
from random import randrange
import numpy as np
from scipy.io.wavfile import write
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

# Maak 4 grafieken aan
fig, ax = plt.subplots(4,figsize=(8, 10))
#plt.subplots_adjust(top=0.95,bottom=0.05,left=0.1,right=0.95,hspace=0.5,wspace=0.1)

plt.tight_layout()

# Laatste grafiek niet plotten (plaats maken voor widgets: knoppen en sliders)
ax[3].axis("off")

# Maak slider toon lengte
time = plt.axes([0.25, 0.2,0.4, 0.02])
s_time = Slider(time, 'tijduur noot [seconden]:', 1, 10, valinit=3)

# Maak slider grondtoon
pitch = plt.axes([0.25, 0.175,0.4, 0.02])
s_pitch = Slider(pitch, 'toonhoogte [Hz]:', 0, 5000, valinit=440, valstep = 1)

# Maak slider harmonics
decayn= plt.axes([0.25, 0.15,0.4, 0.02])
s_decay = Slider(decayn, 'decay [seconden]:', 0,20, valinit=5)


# Maak slider response tijd
responce= plt.axes([0.25, 0.1,0.4, 0.02])
s_responce = Slider(responce, 'echo decay [seconden]: ', 0.001,5, valinit=0.001)

# Maak slider echo intensiteit
inten= plt.axes([0.25, 0.075,0.4, 0.02])
s_intensiteit = Slider(inten, 'echo intensiteit: ', 0,1, valinit=1)


# Maak knot afspelen gecreerde ttom
play = plt.axes([0.75, 0.1, 0.1, 0.075])
b_play = Button(play, 'Play')

# Definieer samplerate:
rate=10000
#geluid=[]

def createmp3(signal, samplerate):
   
    # Geschaalde versie van data (tbv. normalisering)
    scaled = np.int16(signal/np.max(np.abs(signal)) * 32767)
    
    # Wegschrijven van scaled in .mp3 of .wav
    write('my_first_audio.mp3',samplerate,scaled)  
    
    
def mp3play(file):

    # Native player on operating system
    #https://pythonbasics.org/python-play-sound/

    # windows
    os.system("my_first_audio.mp3")

    # linux
    #os.system("mpg123 " + "my_first_audio.mp3")

def updateplot(val):
    
    # Lees waarden van sliders in integers
    time=int(s_time.val)
    pitch=s_pitch.val
    decay=s_decay.val
    responce=s_responce.val
    intensiteit=s_intensiteit.val

    # Maak plotjes leeg
    ax[0].clear()
    ax[1].clear()   
    ax[2].clear()    

    ######################################
    #####Creer sinus net harmonischen#####
    ######################################
    
    # Creer tijd schaal gebaseerd op samplerate
    #time=int(time*pitch)
    t=np.linspace(0,time,int(rate*time))
    
    # Creer grondtoon sinus met frequentie pitch:
    data=np.sin(t*np.pi*pitch*2)    
    
    # Input sinus met exponentiele decay
    data=np.exp(-t*decay*0.5)*data
    
    # Plot Input
    ax[0].set_title("Input: Decayed Sine Wave")
    ax[0].plot(t,data)
   

    ######################################
    ##### Impusle Responce (envelop) #####
    ######################################
    
    # Plot impulse responce signaal
    impulse=np.exp(-t/responce)
     
    ######################################
    ### Moduleer Impulse rand freq.   ####
    ######################################

    #Creer random ruimte met resonantie frequenties    
    random=randrange(5000)
    echo=np.sin(t*np.pi*random*2)

    for i in range(5):
        random=randrange(500)
        echo=echo+np.sin(t*np.pi*random*2)  
 
    echo=impulse*1/5*intensiteit*echo
    ax[1].set_title("Echo Ruimte: Decayed Random Frequenties.")
    ax[1].plot(t,echo)        
        
    
    ######################################
    ##### Convolutie en Signaal      #####
    ######################################   
    
    #Bepaal dubbele tijdschaal door convolutue    
    tijd=np.linspace(0,2*time,-1+int(2*rate*time))
    
    #Bereken de convolutie
    signaal=np.convolve(echo,data,mode="full")
    
    #Plot Grafiek geconvuleerd signaal
    
    ax[2].set_title("Output: Geconvoleerd met echo.")    
    ax[2].plot(tijd,signaal)  
    
    #Creer Wave bestand
    createmp3(signaal,rate)
    
    
# Weergave grafieken eerste keer doorlopen code.
updateplot(1)

# Update grafieken na wijzigen sliders.
s_time.on_changed(updateplot);
s_pitch.on_changed(updateplot);
s_decay.on_changed(updateplot);
s_responce.on_changed(updateplot);
s_intensiteit.on_changed(updateplot);

#Knop afspelen mp3 via operating systeem
b_play.on_clicked(mp3play)

Gebruikersavatar
Berichten: 7.463

Re: Audio en Python

Je nieuwe programma geeft bij mij hetzelfde: maar twee schuifjes, geen play knop, en lege grafieken.

Gebruikersavatar
Berichten: 1.605

Re: Audio en Python

Lijkt erop! Ik neem aan dat je geprobeerd hebt. Zie je verschil?

Gebruikersavatar
Berichten: 7.463

Re: Audio en Python

Ik heb het geprobeerd, en zie geen verschil. Behalve dat nu eerst gevraagd werd het programma op te slaan.

Gebruikersavatar
Berichten: 1.605

Re: Audio en Python

Als je zin hebt kun je deze proberen? Het is een beetje moeilijk debuggen met jouw verouderde mathplotlib (weet niet hoe ik makkelijk kan debuggen zonder een environment aanleggen met oudere versie). Maar misschien een oorzaak gevonden aan de hand van de elementen opbouw jouw screenshot.

Code: Selecteer alles

#V1.02
#Open pyplot in separate interactive window
from IPython import get_ipython
get_ipython().run_line_magic('matplotlib', 'qt5')

import os
from random import randrange
import numpy as np
from scipy.io.wavfile import write
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

# Maak 4 grafieken aan
fig, ax = plt.subplots(4,figsize=(8, 10))
plt.tight_layout()

# Laatste grafiek niet plotten (plaats maken voor widgets: knoppen en sliders)
ax[3].axis("off")

# Tijdsduur noot in seconden
time=2

# Maak slider grondtoon
pitch = plt.axes([0.25, 0.175,0.4, 0.02])
s_pitch = Slider(pitch, 'toonhoogte [Hz]:', 0, 2000, valinit=220)

# Maak slider harmonics
decayn= plt.axes([0.25, 0.15,0.4, 0.02])
s_decay = Slider(decayn, 'decay [seconden]:', 0,0.5, valinit=0.1)

# Maak slider response tijd
responce= plt.axes([0.25, 0.1,0.4, 0.02])
s_responce = Slider(responce, 'echo decay [seconden]: ', 0.001,0.5, valinit=0.001)

# Maak slider echo intensiteit
inten= plt.axes([0.25, 0.075,0.4, 0.02])
s_intensiteit = Slider(inten, 'echo intensiteit: ', 0,1, valinit=1)

# Maak knot afspelen gecreerde ttom
play = plt.axes([0.75, 0.075, 0.1, 0.075])
b_play = Button(play, 'Play')

# Definieer samplerate:
rate=10000
#geluid=[]

def createmp3(signal, samplerate):
   # Geschaalde versie van data (tbv. normalisering)
    scaled = np.int16(signal/np.max(np.abs(signal)) * 32767)
    
    # Wegschrijven van scaled in .mp3 of .wav
    write('my_first_audio.mp3',samplerate,scaled)  
  
def mp3play(file):

    # Native player on operating system
    #https://pythonbasics.org/python-play-sound/

    # windows
    os.system("my_first_audio.mp3")

    # linux
    #os.system("mpg123 " + "my_first_audio.mp3")

def updateplot(val):
    
    # Lees waarden van sliders in integers
    pitch=s_pitch.val
    decay=s_decay.val
    responce=s_responce.val
    intensiteit=s_intensiteit.val

    # Maak plotjes leeg
    ax[0].clear()
    ax[1].clear()   
    ax[2].clear()    

    ######################################
    #####Creeer sinus net harmonischen#####
    ######################################
    
    # Creer tijd schaal gebaseerd op samplerate
    #time=int(time*pitch)
    t=np.linspace(0,time,int(rate*time))
    
    # Creer grondtoon sinus met frequentie pitch:
    data=np.sin(t*np.pi*pitch*2)    
    
    # Input sinus met exponentiele decay
    data=np.exp(-t/decay*0.5)*data
    
    # Plot Input
    ax[0].set_title("Input: Decayed Sine Wave")
    ax[0].plot(t,data)
   

    ######################################
    ##### Impusle Responce (envelop) #####
    ######################################
    
    # Impulse responce signaal
    impulse=np.exp(-t/responce)
     
    ######################################
    ### Moduleer Impulse rand freq.   ####
    ######################################

    #Creer random ruimte met resonantie frequenties    
    random=randrange(5000)
    echo=np.sin(t*np.pi*random*2)

    for i in range(5):
        random=randrange(500)
        echo=echo+np.sin(t*np.pi*random*2)  
 
    echo=impulse*1/5*intensiteit*echo
    ax[1].set_title("Echo Ruimte: Decayed Random Frequenties.")
    ax[1].plot(t,echo)        
        
    
    ######################################
    ##### Convolutie Impuls en Signaal     #####
    ######################################   
    
    #Bepaal dubbele tijdschaal door convolutue    
    tijd=np.linspace(0,2*time,-1+int(2*rate*time))
    
    #Bereken de convolutie
    signaal=np.convolve(echo,data,mode="full")
    
    #Plot Grafiek geconvuleerd signaal
    
    ax[2].set_title("Output: Geconvoleerd met echo.")    
    ax[2].plot(tijd,signaal)  
    
    #Creer Wave bestand
    createmp3(signaal,rate)  
    
# Weergave grafieken eerste keer doorlopen code.
updateplot(1)

# Update grafieken na wijzigen sliders.
s_pitch.on_changed(updateplot);
s_decay.on_changed(updateplot);
s_responce.on_changed(updateplot);
s_intensiteit.on_changed(updateplot);

#Knop afspelen mp3 via operating systeem
b_play.on_clicked(mp3play)
Mocht dit verder werken. Jouw afspeelknop kan mogelijk niet werken. Activeer betreffende Linux lijn in de code (die van win uitschakelen met #):

Code: Selecteer alles

# windows
os.system("my_first_audio.mp3")

# linux
#os.system("mpg123 " + "my_first_audio.mp3")

Gebruikersavatar
Berichten: 7.463

Re: Audio en Python

Dat werkt zo op de kwaliteit van het geluid uit mijn speakers na. De gegenereerde MP3 klinkt wel goed. :D

Gebruikersavatar
Berichten: 1.605

Re: Audio en Python

Het is een beetje behelpen het afspelen .mp3. Dat doen via OS ingestelde afspeel programma (en steeds afsluiten). Om een gehele GUI te maken is wat overkill. Wat dat betreft is het makkelijker in Jupyter notebook.

Ben zelf nog zoekende naar makkelijke afspeel mogelijkheid zoals: playsound. Maar krijg dat nog niet werkende. Vereist tevens een pip install.

Ik zou kunnen voorstellen dat spelen met: DFT/RDFT (Fourier Trans formatie) leuke geluid effecten oplevert. Misschien krijg je goesting zelf iets te gaan proberen.

Er bestaan dan programma's waarmee je dat al kunt doen. Maar soms is het leerzaam zelf te stoeien en een gevoel te krijgen wat het inhoud.

Reageer