Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sound.length not returning correctly #67

Closed
DMB3 opened this issue Nov 22, 2012 · 7 comments
Closed

sound.length not returning correctly #67

DMB3 opened this issue Nov 22, 2012 · 7 comments

Comments

@DMB3
Copy link

DMB3 commented Nov 22, 2012

sound.length seems to always return 1.0 on Android.

https://groups.google.com/forum/?fromgroups=#!topic/kivy-users/Dzf2ubmxILU

Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@tito
Copy link
Member

tito commented Jan 16, 2013

Branch started to fix the issue, but i got weird results. First, we can know the duration of a sound only when it's correctly loaded, any call to the MediaPlayer.getDuration will lead to error like:

E/MediaPlayer(12471): Attempt to call getDuration without a valid mediaplayer
E/MediaPlayer(12471): error (-38, 0)

The question is: should we sync the loading (as pygame does by default) on android? We might get some lag then.
Or should we normalize our Sound API to be async, and then use the Android async feature too?

Also, the duration was correct when playing, but in milliseconds. Then i tried to / 1000. to get seconds, and the division result is just a very weird number. Maybe the java part is wrong.

Anyway, will continue later.

@tito
Copy link
Member

tito commented Jan 16, 2013

@pkor
Copy link

pkor commented Aug 7, 2013

Has there been any change for this? I'm having the same issue and sound length is critical.

@MichaelCurrie
Copy link

I'm hitting this error now, and I'm wondering if it has something to do with Python 2 implicitly casting a float to an integer. Just a thought.

p.s. Once this issue is fixed it would be nice to inform this thread about it too.

@MichaelCurrie
Copy link

@tito Does this kivy/kivy#2776 mean this is taken care of?

@MichaelCurrie
Copy link

As a workaround, I pre-saved all my sound lengths to CSV using the pydub library.

  • All my sounds are .ogg so you'll have to change this if this is not the case for you.
  • I've assumed the media files are all in a folder ../media relative to the location of the below file.
import os, csv
from glob import glob

from pydub import AudioSegment

from flatten import flatten

cur_dir = os.path.dirname(__file__)
media_dir = os.path.join(os.path.dirname(cur_dir), 'media')
sound_paths = (glob(os.path.join(x[0], '*.ogg')) for x in os.walk(media_dir))
# Flatten it, since the lists might contain other lists
south_paths_flattened = list(flatten(sound_paths))

with open('sound_lengths.csv', 'w') as csvfile:
    csvwriter = csv.writer(csvfile, delimiter=',', lineterminator='\n')

    for sound_path in south_paths_flattened:
        print("sound_path: %s" % sound_path)
        try:
            sound = AudioSegment.from_ogg(sound_path)
        except Exception:
            print("Could not load file.")
        else:
            csvwriter.writerow([os.path.normpath(sound_path),
                                str(len(sound) / 1000.)])

Then I load sounds using the static method load of FixedSoundLoader, just the same as if I was going to load the sound with SoundLoader.load.

class FixedSoundLoader(object):
    """
    A custom factory class that substitutes for SoundLoader to avoid issue
    https://github.com/kivy/python-for-android/issues/67

    """
    sound_lengths = {}

    @staticmethod
    def load_sound_lengths():
        with open('sound_lengths.csv', 'r') as csvfile:
            csvreader = csv.reader(csvfile, delimiter=',')
            for row_number, row in enumerate(csvreader):
                print(repr(row))
                FixedSoundLoader.sound_lengths[row[0]] = float(row[1])

    @staticmethod
    def load(sound_file_path):
        sound_file_path = os.path.normpath(sound_file_path)

        if not FixedSoundLoader.sound_lengths:
            FixedSoundLoader.load_sound_lengths()

        sound = SoundLoader.load(sound_file_path)

        try:
            sound_length = FixedSoundLoader.sound_lengths[sound_file_path]
        except KeyError:
            # If we don't have this sound on record in the CSV, hope
            # that the length method actually words
            pass
        else:
            # It's actually the _get_length method we must overrride, as per
            # https://github.com/kivy/kivy/blob/master/
            #                          kivy/core/audio/__init__.py
            sound._get_length = lambda : sound_length

        return sound

@inclement
Copy link
Member

Closing as this issue relates to the old toolchain which is no longer supported. Please open a new issue if you experience this issue with the current master branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants