I'm writing an application for making ringtones for the iPhone. It's just for fun.
Here's what I've done till now. (Mind you, i'm a beginner in Python !)
So I open my mp3 file in binary mode. read the whole file. Convert it into a list. Use list slicing to split the file. Save this new split into a new mp3 file. This works fine. I however want to the ringtones to have a max of 30 seconds play time and I want the user to choose what portion of the file he wants as the ringtone. Can anyone guide me in the right direction ? Thanks
Here's my code till now :
f = open("Bruno Mars - Locked Out Of Heaven [OFFICIAL VIDEO].mp3", 'rb').read()
mp3 = list(f)
fo = open("newFile.mp3", "wb")
print(mp3[0:1300000])
fo.write(bytes(mp3[0:1300000]))
Here's what I got after some coding:
import os
f = open("Bruno Mars - Locked Out Of Heaven [OFFICIAL VIDEO].mp3", 'rb').read()
fileSize = os.path.getsize("Bruno Mars - Locked Out Of Heaven [OFFICIAL VIDEO].mp3")
print("Size of the whole file",fileSize)
mp3 = list(f)
bitRate = int(input("Enter the bit rate of your file"))
size_mbps = bitRate*(15/2048)
print("MB per minute :",size_mbps)
second_size = int((size_mbps/60)*(10**6))
print("Size of each second :",second_size)
start_length = int(input("Enter the start time (in seconds)"))
end_length = int(input("Enter the end time (in seconds)"))
start_size = int(second_size*start_length)
end_size = int(second_size*end_length)
fo = open("newFile.mp3", "wb")
fo.write(bytes(mp3[start_size:end_size]))
It works fine but I need to tweak it a little more. Any input on this code ?
If you want to use a higher-level language like c++ to implement a custom MP3 decoder, take a look a this question, time length of an mp3 file.
Otherwise, there are other libraries that do just what you need:
PyMad -
import mad
mf = mad.MadFile("foo.mp3")
track_length_in_milliseconds = mf.total_time()
audioread -
audio = audioread.audio_open('/path/to/mp3')
print f.channels, f.samplerate, f.duration
Mutagen -
from mutagen.mp3 import MP3
audio = MP3("example.mp3")
print audio.info.length
There are many more, but for now you can start with these.
You have to be a bit careful since mp3 frames do not always stand on their own, which is one of the reasons high end music tools will first convert to WAV or something like it, but as you remarked, it does work up till a certain level.
You could probably benefit from looking at the code in the following project (note that it is GPL licensed though):
http://sourceforge.net/projects/pymp3cut/
the interesting bits:
http://pymp3cut.cvs.sourceforge.net/viewvc/pymp3cut/pymp3cut/pmpcmp3.py?revision=1.2&view=markup
Once you extracted the actual music part, the rough idea is that you base yourself on the bitrate to get the relation between the framesize, seconds, filesize and byte content, which then tells you where to split the bytes to get the starting time and duration that you want.
Related
How can I split midi files based on their pitch using python? I tried the music21 library, but I don't really know how this works...
Try this code:
import pretty_midi
import copy
pitch_cutoff = 65
mid = pretty_midi.PrettyMIDI('my_file.mid')
low_notes = copy.deepcopy(mid)
high_notes = copy.deepcopy(mid)
for instrument in low_notes.instruments:
for note in instrument.notes:
if note.pitch > pitch_cutoff:
note.velocity = 0
for instrument in high_notes.instruments:
for note in instrument.notes:
if note.pitch < pitch_cutoff:
note.velocity = 0
low_notes.write("low_notes.mid")
high_notes.write("high_notes.mid")
it uses the pretty_midi module to split a midi file into two different files. The file called "high_notes.mid" will only have notes above what you set the pitch_cutoff variable to, and "low_notes.mid" will only have notes below that. Just change "my_file.mid" to whatever the name of your file is and try it out. Let me know if you have any questions.
I have a script to write musical notes to a directory based on the byte object returned from my HTTP request. The problem I am having is that the .ogg sound file is 5 seconds long and ideally I would like to shorten this to 0.5 seconds. Is this possible to do so by simply dropping chunks of the byte object?
I know via pysoundfile it is possible to use the frames and sample rate to calculate duration and therefore write 'x' frames. This is only possible for static rates however and the sample rate for these files are not known due to the musical notes being extracted in raw form.
Some of the code I have written is below.
for notenumbers in range(48, 64+1):
note = requests.get(url.format(instrument, notenumbers))
notebinary = note.content
time.sleep(3)
with open("E:\\useraccount\\x\\x\\"+str(dirname)+"\\"+str(instrname)+"\\"+str(instrname) +"-" +str(notenumbers) +".ogg", "wb") as o:
print("Creating file named: " +str(instrname) +":" +str(notenumbers) +".ogg")
o.write(notebinary)
Thank you if you are able to help with this!
Here's my problem. I have a huge number of waveform files of the same phrases in different languages and want to write a python script so that I can choose the phrase and language combinations and the script will build and export an mp3 file with the waveform phrases next to each other. The outputted file would for example, have the phrase 'nice to meet you' in English followed by it's equivalent in Japanese after a pause of 2 seconds, followed by the next item in the list with it's equivalent in Japanese. I want to know if there is a library that I need to do this or whether it can be written with the standard python library. Thanks to anyone who can help.
You can try using dictionaries so, y = {"hello":"hola","etc"} And when one is called you can then convert it to the sound file. For example, if you are on a mac you can do
from os import system
system('say '+ hello)
This only works on a mac though.
I hope this helped however, you didn't mention what you have already tried, so I can't get anymore specific.
FFmpeg
http://ffmpeg.org/
Is a great solution for handling audio conversions with Python.
There are multiple ways to do this. However, I have found pydub to be easiest for audio manipulation. Especially for slicing and joining.
You can install using
pip install pydub #for 2.x
pip3 install pydub # for 3.x
Suppose your files are as below,
your phrase in English = "nice_to_meet_you_eng.mp3"
And your phrase in Japanese = "nice_to_meet_you_jap.mp3"
You can use following example to join English phrase , followed by a 2 second delay and then Japanese phrase.
** This code is not tested **
from pydub import AudioSegment
from pydub.playback import play
#Create audio segments for audio files
nice_to_meet_you_eng = AudioSegment.from_mp3("nice_to_meet_you_eng.mp3")
nice_to_meet_you_jap = AudioSegment.from_mp3("nice_to_meet_you_jap.mp3")
#create two seconds of delay
two_second_of_silence = AudioSegment.silent(duration=2000) # duration in millisec
#concatenate segments as per requirement
myphrase =nice_to_meet_you_eng + two_second_of_silence + nice_to_meet_you_jap
#Export combined phrase
myphrase.export("myphrase.mp3", format="mp3")
#play combined phrase
play(myphrase)
I'm trying to make a siren sound in python with beeps, but had no success..
I'm trying something like
winsound.Beep(700,500)
winsound.Beep(710,500)
winsound.Beep(720,500)
...
It's a better way to do it? And play it?
Without external files...
Thx
Record a high quality siren as a WAV file (Audacity is a nice tool for this task, and might even provide the right mix of sound generators for this) and use PlaySound.
winsound.PlaySound('siren.wav', winsound.SND_FILENAME)
You could also bundle it into the script as a string to avoid having a separate file:
siren = base64.b64decode('''
<base64-encoded data>
''')
winsound.PlaySound(siren, winsound.SND_MEMORY)
To create the data for siren, run the WAV file through a base64 encoder (e.g., here is a basic command-line tool — the download includes a win32 exe) and paste the output into the siren string. Base64 isn't a requirement, by the way; it's just a convenient way to embed binary data into a Python source file.
I remember using something similar on QBASIC when I was still a kid:
DO
FOR n = -180 TO 180 STEP .1
f = 440 + 50 * SIN(n)
SOUND f, 1
NEXT
LOOP
SOUND f, 1 should be the same thing as winsound.Beep, with pitch and duration. It used to work great but since I took the snippet here I'm not sure I did exactly this way.
It's just to give you the idea..
I have these files with the extension ".adc". They are simply raw data files. I can open them with Audacity using File->Import->Raw data with encoding "Signed 16 bit" and sample rate "16000 Khz".
I would like to do the same with python. I think that audioop module is what I need, but I can't seem to find examples on how to use it for something that simple.
The main goal is to open the file and play a certain location in the file, for example from the second 10 to the second 20. Is there something out there for my task ?
Thanx in advance.
For opening the file, you just need file().
For finding a location, you don't need audioop: you just need to convert seconds to bytes and get the required bytes of the file. For instance, if your file is 16 kHz 16bit mono, each second is 32,000 bytes of data. So the 10th second is 320kB into the file. Just seek to the appropriate place in the file and then read the appropriate number of bytes.
And audioop can't help you with the hardest part: namely, playing the audio. The correct way to do this very much depends on your OS.
EDIT: Sorry, I just noticed your username is "thelinuxer". Consider pyAO for playing audio from Python on Linux. You will probably need to change the sample format to play the audio---audioop will help you with this (see ratecv, tomono/tostereo, lin2lin, and bias)
Thanx a lot I was able to do the following:
def play_data(filename, first_sec, second_sec):
import ao
from ao import AudioDevice
dev = AudioDevice(2, bits=16, rate=16000,channels=1)
f = open(filename, 'r')
data_len = (second_sec-first_sec)*32000
f.seek(32000*first_sec)
data = f.read(data_len)
dev.play(data)
f.close()
play_data('AR001_3.adc', 2.5, 5)
You can use PySoundFile to open the file as a NumPy array and play it with python-sounddevice.
import soundfile as sf
import sounddevice as sd
sig, fs = sf.read('myfile.adc', channels=2, samplerate=16000,
format='RAW', subtype='PCM_16')
sd.play(sig, fs)
You can use indexing on the NumPy array to select a certain part of the audio data.