( Sorry for double post, please remove the same thread in game WIP and demos)
# Music script by RockyMadio #
import wave
import contextlib
import GameLogic
import aud
cont = GameLogic.getCurrentController()
own = cont.owner
fname = own['songpath'] # will be changed in future
own['timer'] = 0
with contextlib.closing(wave.open(fname,'r')) as f:
frames = f.getnframes()
rate = f.getframerate()
duration = frames / float(rate)
cont.owner["length"] = duration
# Total duration #
minutes = int(own['length']/60)
seconds = int(own['length']%60)
own['reallength'] = str(minutes) + ":" + str("%02i"% seconds)
# Play the song #
song = aud.Factory.file(fname)
aud.device().play(song)
Hi everyone,
i made this script to calculate the length of any audio (wave type) for my music game. The script works well, but anyway the wave file is kinda too large for the game, even that i just resized all of them. I think there should be a way to turn this script into another version for mp3 file.
(I really need the length to limit the beat map i made for the note patterns and to end the track)
I thank you in advance.
Hi, I’m not that great with audio stuff, but I can tell you what I’d do…
It’s amazing that you managed to get the length of the track by python, but are you sure that you need to?
Looking at your dance project it seems like you’re using songs that already exist, rather than generating your own dynamically. In that case you can get the song length in windows explorer, you don’t need to get it in game.
I’d just write a short dictionary with some data about the songs I was using:
song_data = {"voodoo_people":{"artist":"The Prodigy","title":"Voodoo People (Original)","length":18540},
"dont_stop_me_now":{"artist":"Queen","title":"Don't Stop Me Now","length":13020}}
I’m sorry I don’t have any more useful advice about decoding data from mp3s, it’s not something I’ve tried before.
BTW: If you’re using MP3s, you should be careful, because when i used them in the past through blender’s normal sound system they sometimes took a bit of time to initiate. I don’t know why, or if it is something that has been fixed, but it could cause problems with your timing…
i kinda need the total duration of a track to limit the beat map, because the longer the music is being played, the longer the beatmap file still runs. I want to stop everything and let a result board appear, when the music timer touches the total duration of the song.
To get the duration of these variably-compressed sound files you basically have to parse over the whole thing. I’d suggest picking up a 3rd-party library to handle the work for you, like this: https://github.com/devsnd/tinytag
Unless you plan on supporting custom songs, it may be easier to include per-song configuration with duration, name, etc.
It’s pure-python, so you need only copy the tinytag folder alongside the .blend and use like so:
from tinytag import TinyTag
tag = TinyTag.get('/some/music.mp3')
print('This track is by %s.' % tag.artist)
print('It is %f seconds long.' % tag.duration)
I should note the MP3 patent holder wants royalties after distributing 5000 copies of the game.
Might consider ogg vorbis instead, it’s the non-evil open source alternative.
Yeah, unless you want players to be able to upload their own songs or some thing like that (actually that might be a good way to get around copyright issues, just allow people to put MP3s or wavs in a folder and play them from there…)
Basically there’s two types of content you have to deal with in a game, pre-generated or dynamic.
Randomly generated levels or songs would be dynamic content, as would user uploaded songs.
Songs packed in and shipped with a game would be pregenerated content.
You only have to do on the fly calculations for dynamic content. everything else it’s better to do the calculations before packing the game. Otherwise it just increases loading time, and it’s the same data every time right?
song duration in seconds * 60 frames per second = song duration in blender logic frames
Though a slow frame rate could cause the game to go out of sinc… which wouldn’t be good.
min,sec = duration.split(":")
fps=60 # your fps setting
dtime=(min*60+sec)*fps
edit:
And as said before:
If you use mp3 or ogg files, their decoding get time in the beginning.
Decoder must decode at least one frame, before it goes to audiobuffer.
I strongly advice to use aud library, with buffered option.
This is when timing needs accurate.
you are right. the mp3 file really delays like about 0.3 secibd and all the beat maps i created for the music game also follow behind it, and give offbeat effects too. With regular wave file it really loads very fast.
I reduced the wave files with its sample rate from 44100 to 11025 Hz. The quality is kinda abit unclear compared to the original file. but its still acceptable and causes no noise in the game.
All the tracks i use for the game is just about 2 minutes. so each file just contains about 3 - 4 mb
Playing music with aud (audaspace) not so hard.
11 khz is very low, Sound quality goes below poorest c-cassette, just my thoughts.
device = aud.device()
factory = aud.Factory(bge.logic.expandPath('//Music/Musica.ogg'))
factory_buffered = aud.Factory.buffer(factory)
#We get whole audio file to memory, it eats memory, timing is so important
#
#Here is place when you set reset counter
#
handle = device.play(factory_buffered) #Just lauch preloaded song