0

I am looking to combine 10 audio samples in various manners (format - wav probably, but this can be changed to any format as they will be pre-recorded).

from pydub import AudioSegment sounds = [] sound1 = AudioSegment.from_wav("Dropbox/PIREAD/1.wav") sound2 = AudioSegment.from_wav("Dropbox/PIREAD/2.wav") sound3 = AudioSegment.from_wav("Dropbox/PIREAD/3.wav") sound4 = AudioSegment.from_wav("Dropbox/PIREAD/4.wav") sound5 = AudioSegment.from_wav("Dropbox/PIREAD/5.wav") sound6 = AudioSegment.from_wav("Dropbox/PIREAD/6.wav") sound7 = AudioSegment.from_wav("Dropbox/PIREAD/7.wav") sound8 = AudioSegment.from_wav("Dropbox/PIREAD/8.wav") sound9 = AudioSegment.from_wav("Dropbox/PIREAD/9.wav") sound0 = AudioSegment.from_wav("Dropbox/PIREAD/0.wav") sounds=[sound1,sound2,sound3,sound4,sound5,sound6,sound7,sound8,sound9,sound0] combined_sounds = AudioSegment.empty() for x in range(10): for y in range(10): combined_sounds += sounds[y] combined_sounds.export("Dropbox/PIREAD/joinedFile.wav", format="wav") 

This is literally me reading the numbers 0-9 and assembling them into one overall wav file.

It works - but it is slow once the loop is extended x=100, x=1000.

Q: How can I speed things up?

The actual order of the numbers will be read from a text$ - for example "354224848179261915075" which happens to be the 100th Fibonacci number.

Cheers Glen

2
  • 1
    Why are you doing a double loop? If you want 1-10 and then 1-10 again and again 10 times total, then it would be better to just re-add 10-element segment later, rather than go through all 10 files again. (The difference is: going 10^2 times or going 2*10 times) Commented Oct 20, 2021 at 11:23
  • See below - was just testing for speed. DOH!!! should have though BigO before I asked. Commented Oct 20, 2021 at 11:30

3 Answers 3

1

I believe it's slow because when you loop over x, you repeat operations (the loop over y) which could be computed before the loop over x, then assembled.

Sign up to request clarification or add additional context in comments.

7 Comments

The nested for's are for testing. What I want to achieve is parse a string - "num = 123456789" and to assemble a spoken representation of this. The only thing being that the number will be 1000s of characters long.
So - can iterate over the characters in the num and pull those wav files from a dict? and then assemble them. Will get on and test.
Maybe you could explain what you are trying to do: seems like you're trying to create an acoustic representation of the Fibo sequence (neat project!). I believe if you try low numbers, like the first 10 numbers of the sequence, this program should stop pretty quicly. From which step does your program feel slow?
Exactly this... In different accents, different languages, different genders etc etc My for loop was to generate numbers to test -- what I will do is to change this to the actual Fib numbers --- only one loop then to iterate over the digits.
Beware of how you're computing the Fib sequence, this could be the step that's slowing your program ;)
|
1

I looked into AudioSegment and found potentially useful method for you namely from_mono_audiosegments but it is limited to mono sounds and you will need to test if it is faster than += please compare time-wise these options, i.e.

import time from pydub import AudioSegment sounds = [] sound1 = AudioSegment.from_wav("Dropbox/PIREAD/1.wav") sound2 = AudioSegment.from_wav("Dropbox/PIREAD/2.wav") sound3 = AudioSegment.from_wav("Dropbox/PIREAD/3.wav") sound4 = AudioSegment.from_wav("Dropbox/PIREAD/4.wav") sound5 = AudioSegment.from_wav("Dropbox/PIREAD/5.wav") sound6 = AudioSegment.from_wav("Dropbox/PIREAD/6.wav") sound7 = AudioSegment.from_wav("Dropbox/PIREAD/7.wav") sound8 = AudioSegment.from_wav("Dropbox/PIREAD/8.wav") sound9 = AudioSegment.from_wav("Dropbox/PIREAD/9.wav") sound0 = AudioSegment.from_wav("Dropbox/PIREAD/0.wav") sounds=[sound1,sound2,sound3,sound4,sound5,sound6,sound7,sound8,sound9,sound0] # option1 using += t1 = time.time() combined_sounds1 = AudioSegment.empty() for s in sounds combined_sounds1 += s t2 = time.time() # end of option1 # option2 using from_mono_audiosegments t3 = time.time() combined_sounds2 = AudioSegment.from_mono_audiosegments(*sounds) t4 = time.time() # end of option2 print('option1 (seconds):',t2-t1) print('option2 (seconds):',t4-t3) 

1 Comment

Nice - every little helps (speed I mean - the help is greatly appreciated) -- will update with progress. TY
1

Thanks for the suggestions and advice above. This is the final code I used and link to the resultant video (with ffmpeg visualisation):

# Program to display the Fibonacci sequence up to n-th term from pydub import AudioSegment combined_sounds = "" sound1 = AudioSegment.from_wav("1_2.wav") sound2 = AudioSegment.from_wav("2_2.wav") sound3 = AudioSegment.from_wav("3_2.wav") sound4 = AudioSegment.from_wav("4_2.wav") sound5 = AudioSegment.from_wav("5_2.wav") sound6 = AudioSegment.from_wav("6_2.wav") sound7 = AudioSegment.from_wav("7_2.wav") sound8 = AudioSegment.from_wav("8_2.wav") sound9 = AudioSegment.from_wav("9_2.wav") sound0 = AudioSegment.from_wav("0_2.wav") nterms=1000 # first two terms n1, n2 = 0, 1 count = 0 fib = "" # check if the number of terms is valid if nterms <= 0: print("Please enter a positive integer") # if there is only one term, return n1 elif nterms == 1: print("Fibonacci sequence upto",nterms,":") print(n1) # generate fibonacci sequence else: print("Fibonacci sequence:") while count < nterms: #print(n1) fib += str(n1) nth = n1 + n2 # update values n1 = n2 n2 = nth count += 1 i=-36 j=0 fibs = [fib[i:i+1000] for i in range(0, len(fib), 1000)] seg = 0 for a in fibs: if seg == 2: break combined_sounds = AudioSegment.empty() seg +=1 for x in a: i,j = -36,0 s = eval("sound"+str(x)) s = s.apply_gain_stereo(i,j) combined_sounds += s i,j = j,i combined_sounds.export("joinedFile"+str(seg)+".wav", format="wav") 

This splits the output into 1000 digit wav files. The first 1000 Fibonacci terms produces nearly 15Gb of wavs!

Uploaded to YouTube: https://www.youtube.com/watch?v=U7Z_HOGqjlE

Thanks all.

2 Comments

Can I make my own reply the accepted answer - apologies for my lack of SO-fu
Absolutely. Self-answering is encouraged, self-acceptance is too.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.