Search code examples
pythonaudiojupyter-notebookipythonscheduled-tasks

Using IPython.display.audio to play audio in jupyter notebook not working when used inside a function


When using the code below the sound plays:

import IPython.display as ipd
import numpy

sr = 22050 # sample rate
T = 0.5    # seconds
t = numpy.linspace(0, T, int(T*sr), endpoint=False) # time variable
x = 0.5*numpy.sin(2*numpy.pi*440*t)              # pure sine wave at 440 Hz
ipd.Audio(x, rate=sr, autoplay=True) # load a NumPy array

But when I use it inside a function it stops working:

import IPython.display as ipd
import numpy

def SoundNotification():
    sr = 22050 # sample rate
    T = 0.5    # seconds
    t = numpy.linspace(0, T, int(T*sr), endpoint=False) # time variable
    x = 0.5*numpy.sin(2*numpy.pi*440*t)              # pure sine wave at 440 Hz
    ipd.Audio(x, rate=sr, autoplay=True) # load a NumPy array

SoundNotification()

I've tried to assign the audio to a variable and return it which works:

import IPython.display as ipd
import numpy

def SoundNotification():
    sr = 22050 # sample rate
    T = 0.5    # seconds
    t = numpy.linspace(0, T, int(T*sr), endpoint=False) # time variable
    x = 0.5*numpy.sin(2*numpy.pi*440*t)              # pure sine wave at 440 Hz
    sound = ipd.Audio(x, rate=sr, autoplay=True) # load a NumPy array
    return sound
sound = SoundNotification()
sound

But I want to use the sound in a different function:

import IPython.display as ipd
import numpy

def SoundNotification():
    sr = 22050 # sample rate
    T = 0.5    # seconds
    t = numpy.linspace(0, T, int(T*sr), endpoint=False) # time variable
    x = 0.5*numpy.sin(2*numpy.pi*440*t)              # pure sine wave at 440 Hz
    sound = ipd.Audio(x, rate=sr, autoplay=True) # load a NumPy array
    return sound

def WhereIWantToUseTheSound():    
    sound = SoundNotification()
    sound

WhereIWantToUseTheSound()

How do I make this work and what causes this behavior? The kernel for the notebook is Python 3.

Edit: I want to play the sound in a scheduled event:

import IPython.display as ipd
import numpy
import sched, time

sound = []
def SoundNotification():
    sr = 22050 # sample rate
    T = 0.5    # seconds
    t = numpy.linspace(0, T, int(T*sr), endpoint=False) # time variable
    x = 0.5*numpy.sin(2*numpy.pi*440*t)              # pure sine wave at 440 Hz
    sound = ipd.Audio(x, rate=sr, autoplay=True) # load a NumPy array
    return sound


def do_something(sc): 
    print("Doing stuff...")
    # do your stuff
    sound_ = SoundNotification()
    s.enter(interval, 1, do_something, (sc,))
    return sound_


s = sched.scheduler(time.time, time.sleep)
interval = int(input("Interval between captures in seconds: "))
s.enter(0, 1, do_something, (s,))
s.run()

I don't know how to return the sound and schedule the next event within the same function.


Solution

  • I was having this same problem, the sound was played when I called:

    from IPython.display import Audio 
    Audio('/path/beep.mp3', autoplay=True)
    

    But it didn't work when it was inside a function. The problem is that the function call doesn't really play the sound, it's actually played by the resulting HTML that is returned to Jupyter output.

    So to overcome this, you can force the function to render the HTML using display( ) function from IPython. This will work:

    from IPython.display import Audio 
    from IPython.core.display import display
    def beep():
        display(Audio('/path/beep.mp3', autoplay=True))
    beep();