0

I want to create a filelike object that will later be opened by its filename. Is it possible to do that? I'm looking for something like this:

import io

fileLikeObject = io.BytesIO()
fileLikeObject.write((b"randomContent")
fileLikeObject.name = "someFilename.txt"

sameFileAsbefore = open("someFilename.txt", "rb")
sameFileAsbefore.read()

I've looked at this thread, but the file is not accessible by its name afterwards.

For completeness, what I want to specifically do is to generate a sinusoidal waveform and play in an Android environment. Here is a code adapted from this answer.

from kivy.core.audio import SoundLoader
from kivy.base import runTouchApp
from kivy.uix.button import Button
import time


# Wave parameters
fs = 44100 # sampling frequency
duration = 2 # seconds

# Generating waveforms
timePoints = np.linspace(0, duration, duration*fs)
sineWave = np.sin(2 * np.pi * 440 * timePoints) # 440 Hz
outdata = np.transpose(np.tile(volume*outputWave, (2,1)))

class MyLabel(Button):
    def on_release(self):
        start_time = time.time()
        self.play_sound()
        print("--- %s seconds ---" % (time.time() - start_time))

    def play_sound(self):

        bytes_out = io.BytesIO()
        wavfile.write(bytes_out, fs, outdata)
        bytes_out.seek(0)

        sound = SoundLoader.load(bytes_out) # only loads by filename :/
        sound.seek(0)

        if sound:
            print("Sound found at %s" % sound.source)
            print("Sound is %.3f seconds" % sound.length)
            sound.play()

runTouchApp(MyLabel(text="Press me for a sound"))

I'm also open to other solutions that allow me to play machine-generated sounds on Android. Thanks for helping!

lljotall
  • 1
  • 1
  • So write the data to a file? – Aran-Fey Aug 04 '18 at 11:07
  • What i understood is that you need to load sound from memory and there is no direct way to do it, i think a cheap hack would be to create a local tmp directory where you save these files and load them, then clean it on 'app.on_stop'. – hchandad Aug 05 '18 at 07:27

1 Answers1

0

As the saying goes, "premature optimization is the source of all evil", right?

Based on @fins' comment, I've created temporary files to store the audio using the library tempfile. It automatically destroys the file when it is closed.

Here's the working version for what I've posted in the question:

from kivy.core.audio import SoundLoader
from kivy.base import runTouchApp
from kivy.uix.button import Button
from scipy.io import wavfile
import time
import tempfile
import numpy as np

# Wave parameters
fs = 44100 # sampling frequency
duration = 2 # seconds

# Generating waveforms
timePoints = np.linspace(0, duration, duration*fs)
sineWave = np.sin(2 * np.pi * 440 * timePoints) # 440 Hz
outdata = np.transpose(np.tile(sineWave, (2,1)))

class MyLabel(Button):
    def on_release(self):
        start_time = time.time()
        self.play_sound()
        print("--- %s seconds ---" % (time.time() - start_time))

    def play_sound(self):

        f = tempfile.NamedTemporaryFile(suffix = '.wav', delete=True)
        wavfile.write(f, fs, outdata)
        f.seek(0)

        sound = SoundLoader.load(f.name)

        if sound:
            print("Sound found at %s" % sound.source)
            print("Sound is %.3f seconds" % sound.length)
            sound.play()

        f.close()

runTouchApp(MyLabel(text="Press me for a sound"))
lljotall
  • 1
  • 1