SRL-Forums  

Welcome to the SRL! ...SRL Repository ... SRL forums have opened up for registration again! ... Make sure you check out Simba

Go Back   SRL-Forums > Programming > Programming > Python Programming
Python Programming For all your python programs.



Reply
 
Thread Tools
(#1)
Old
Wizzup?'s Avatar
Wizzup? Wizzup? is offline
Administrator
SRL Old Timer SRL DonatorSRL ScripterSRL DeveloperAdministrator
Corporeal Beast
Wizzup? has disabled reputation
 
Activity Longevity
18/20 20/20
Today Posts
0/5 sssss9649
Send a message via ICQ to Wizzup?
Default Voice Activated Recording for the Nokia N900 / Linux Desktop. - 07-26-2010, 09:37 PM

I had been looking a long time for a program that would start recording, but only save frames that contain sound which is ``louder'' than a specific threshold. I searched for programs. I found none that were open source. There weren't any closed source ones that run on linux or my n900 either... Only a few heavy programs for Windows. (Which were closed)

Why do I want this? Well.. very often I have some great ideas or just plain things I want to remember. When I'm walking in the forest, sitting in bath, cycling in the city... (Or just sitting in my room, music playing doesn't bother it) Then I can't just write it down. So this is kind of a Memo application, but instead of typing, you just say whatever you want to say, and it will record that. It will obviously have to be on all the time, but it will only actually save the useful samples.

So... I knew my phone could record because it had some "recorder" app. It worked quite well, but did not have this particular feature. I found the source, and it was written in C. It seemed to use GStreamer for recording, in combination with PulseAudio. (My phone uses PulseAudio)

I was messing a bit with GStreamer, but it was a bit overkill and didn't send any WAVE headers either. So I fell back to a default linux program. (It's probably on your desktop too, if you run Linux): asound. This program simply dumps the raw .wav file to the standard output. So I made a subprocess in my python script which piped all the wave output to my program. My program will read 8000 samples at a time, - exactly 1 second -and then process it. If it contains at least one high and low tone, it will write the entire sample of one second to the output file. Additionally, it will always record one extra second after a second that contain a loud sound. If that extra second also contains loud sounds, it will also capture the next second, and so on.

It was quite a task to do this, as I first didn't take a good look at my output data and started to do Fast Fourier Transformations, while I did not even need these.

Simply run the program by either making it executable (chmod +x the_file) or call it like "python the_file".
Obviously it will need a GUI and a system to manage all the output files, as it will currently override the last session. It should probably not write output to the file as it does now... More buffering would be more flash card friendly.

Some credits go to Benland100 for flaming/teasing me when I was using FFTs to do this. He put me on the right track.

E: Obviously this will work on any system that has asound and python.

python Code:
#!/usr/bin/env python

import subprocess
import wave
import time

#p = subprocess.Popen(['gst-launch-0.10', 'pulsesrc ! wavenc ! fdsink fd=1'], \
#                stdout=subprocess.PIPE)

# Arecord just dumps the raw wav to stdout. We will use this
# to read from with out wave module.
p = subprocess.Popen(['arecord'], stdout=subprocess.PIPE)

# Open the pipe.
f = wave.open(p.stdout)

# Open file we will write to.
o = wave.open('test.wav', 'w')
o.setparams((1, 1, 8000, 0, 'NONE', 'not compressed'))
o.setnchannels(1)

high, lasthigh = False, False

# Print audio set up
print f.getparams()

while True:
    # Read 1 second
    a = f.readframes(8000)
    b = [ord(x) for x in a]
    _min, _max = min(b), max(b)

    # Print bounds
    print 'min', _min
    print 'max', _max

    # TODO: The gate should obviously be configurable.
    if _max > 135 and _min < 120:
        high = True
    else:
        high = False

    # Write always if either is True.
    if lasthigh or high:
        o.writeframes(a)

    lasthigh = high

f.close()
o.close()

Last edited by Wizzup?; 07-27-2010 at 12:05 AM.
Reply With Quote
(#2)
Old
mastaraymond's Avatar
mastaraymond mastaraymond is offline
SRL Developer / Lazy Mod
SRL Old Timer SRL Competition WinnerSRL Tutorial WriterSRL MasterSRL ScripterSRL DeveloperModerator
Tormented Demon
mastaraymond is a jewel in the roughmastaraymond is a jewel in the roughmastaraymond is a jewel in the rough
 
Activity Longevity
6/20 19/20
Today Posts
0/5 sssss3386
Send a message via MSN to mastaraymond
Default 07-26-2010, 09:49 PM

Is this the answer of life?


Follow Simba development on Twitter!
Reply With Quote
(#3)
Old
i luffs yeww's Avatar
i luffs yeww i luffs yeww is offline
SRL Junior Member
SRL Donator
Lesser Demon
i luffs yeww has a spectacular aura abouti luffs yeww has a spectacular aura abouti luffs yeww has a spectacular aura about
 
Activity Longevity
17/20 3/20
Today Posts
1/5 sssss2642
Default 07-26-2010, 10:07 PM

My phone is a joke, but this really excited me. :3 I'd like to have a phone up to today's standards and be able to experiment with this.

Great job! And it sounds really interesting. ^^

Python Code:
if max(b) > 135 and min(b) < 120:
  high = True
else:
  high = False

#Could simply be

high = max(b) > 135 and min(b) < 120

#no?
 


Quote:
Originally Posted by Nava2 View Post
Thats why there was so much confusing lololol.
Quote:
Originally Posted by Wizzup? View Post
And waste so many power?

Last edited by i luffs yeww; 07-26-2010 at 10:12 PM.
Reply With Quote
(#4)
Old
Awkwardsaw's Avatar
Awkwardsaw Awkwardsaw is online now
SRL Member
SRL Old Timer SRL AristocratSRL Donator
Lesser Demon
Awkwardsaw has disabled reputation
 
Activity Longevity
8/20 15/20
Today Posts
1/5 sssss1951
Send a message via MSN to Awkwardsaw
Default 07-26-2010, 10:09 PM

Quote:
Originally Posted by i luffs yeww View Post
My phone is a joke, but this really excited me. :3 I'd like to have a phone up to today's standards and be able to experiment with this.

Great job! And it sounds really interesting. ^^
i have the same phone, cept its black

its legit, does every thing i need



her: aw this song is so cute
me: yeah, nothing cuter than meticulously planning to murder your children
Reply With Quote
(#5)
Old
Craig` Craig` is offline
SRL Junior Member
SRL Donator
Chicken
Craig` is on a distinguished road
 
Activity Longevity
7/20 8/20
Today Posts
0/5 ssssss194
Default 07-26-2010, 10:10 PM

nice.
Reply With Quote
(#6)
Old
i luffs yeww's Avatar
i luffs yeww i luffs yeww is offline
SRL Junior Member
SRL Donator
Lesser Demon
i luffs yeww has a spectacular aura abouti luffs yeww has a spectacular aura abouti luffs yeww has a spectacular aura about
 
Activity Longevity
17/20 3/20
Today Posts
1/5 sssss2642
Default 07-26-2010, 10:13 PM

Awkward, mine's black, too!

/spam


Quote:
Originally Posted by Nava2 View Post
Thats why there was so much confusing lololol.
Quote:
Originally Posted by Wizzup? View Post
And waste so many power?
Reply With Quote
(#7)
Old
Wizzup?'s Avatar
Wizzup? Wizzup? is offline
Administrator
SRL Old Timer SRL DonatorSRL ScripterSRL DeveloperAdministrator
Corporeal Beast
Wizzup? has disabled reputation
 
Activity Longevity
18/20 20/20
Today Posts
0/5 sssss9649
Send a message via ICQ to Wizzup?
Default 07-26-2010, 10:25 PM

Quote:
Originally Posted by i luffs yeww View Post
My phone is a joke, but this really excited me. :3 I'd like to have a phone up to today's standards and be able to experiment with this.

Great job! And it sounds really interesting. ^^

Python Code:
if max(b) > 135 and min(b) < 120:
  high = True
else:
  high = False

#Could simply be

high = max(b) > 135 and min(b) < 120

#no?
 
Yes. And the *.close() methods on f and o can be removed as well, as the only way to exit the program currently it to use ctrl+c, which will stop the program immediately. (Python will call .close though) The loop should catch the Ctrl+c exception and then break though.
Reply With Quote
(#8)
Old
i luffs yeww's Avatar
i luffs yeww i luffs yeww is offline
SRL Junior Member
SRL Donator
Lesser Demon
i luffs yeww has a spectacular aura abouti luffs yeww has a spectacular aura abouti luffs yeww has a spectacular aura about
 
Activity Longevity
17/20 3/20
Today Posts
1/5 sssss2642
Default 07-26-2010, 10:29 PM

Thanks for the info.


Quote:
Originally Posted by Nava2 View Post
Thats why there was so much confusing lololol.
Quote:
Originally Posted by Wizzup? View Post
And waste so many power?
Reply With Quote
(#9)
Old
Wizzup?'s Avatar
Wizzup? Wizzup? is offline
Administrator
SRL Old Timer SRL DonatorSRL ScripterSRL DeveloperAdministrator
Corporeal Beast
Wizzup? has disabled reputation
 
Activity Longevity
18/20 20/20
Today Posts
0/5 sssss9649
Send a message via ICQ to Wizzup?
Default 07-26-2010, 10:47 PM

Also, I'm not sure if asound always records @ 8000 samples. Probably not, so I'll have to change that as well. Will test tomorrow with my laptop.
Reply With Quote
(#10)
Old
R0b0t1's Avatar
R0b0t1 R0b0t1 is offline
Senior SRL Member
SRL Old Timer SRL HelperSRL Tutorial Writer
Chicken
R0b0t1 has disabled reputation
 
Activity Longevity
6/20 17/20
Today Posts
0/5 sssss3642
Default 07-27-2010, 12:05 AM

python Code:
import magic


The jealous temper of mankind, ever more disposed to censure than
to praise the work of others, has constantly made the pursuit of new
methods and systems no less perilous than the search after unknown
lands and seas.
Reply With Quote
(#11)
Old
moser moser is offline
Registered User
Chicken
moser is on a distinguished road
 
Activity Longevity
1/20 1/20
Today Posts
0/5 ssssssss5
Default 07-27-2010, 04:49 PM

Thanks for this. How do you change the recording parameters? Other than the "8000" in the line below which is obviously the sample rate, what do the other numbers control? I want to be able to change the bit depth to 16 per sample and the channels to 2. I'm no stranger to arecord, but I don't understand python.

o.setparams((1, 1, 8000, 0, 'NONE', 'not compressed'))
Reply With Quote
(#12)
Old
moser moser is offline
Registered User
Chicken
moser is on a distinguished road
 
Activity Longevity
1/20 1/20
Today Posts
0/5 ssssssss5
Default 07-28-2010, 05:32 AM

I found this http://docs.python.org/library/wave.html.

But when I change the line o.setparams((1, 1, 8000, 0, 'NONE', 'not compressed')) to o.setparams((1, 2, 8000, 0, 'NONE', 'not compressed')), the audio just becomes garbled.

Also, changing the 8000 in both places in the script doesn't work, it just makes the audio sound like the chipmunks.
Reply With Quote
(#13)
Old
Wizzup?'s Avatar
Wizzup? Wizzup? is offline
Administrator
SRL Old Timer SRL DonatorSRL ScripterSRL DeveloperAdministrator
Corporeal Beast
Wizzup? has disabled reputation
 
Activity Longevity
18/20 20/20
Today Posts
0/5 sssss9649
Send a message via ICQ to Wizzup?
Default 07-28-2010, 09:12 AM

Quote:
Originally Posted by moser View Post
I found this http://docs.python.org/library/wave.html.

But when I change the line o.setparams((1, 1, 8000, 0, 'NONE', 'not compressed')) to o.setparams((1, 2, 8000, 0, 'NONE', 'not compressed')), the audio just becomes garbled.

Also, changing the 8000 in both places in the script doesn't work, it just makes the audio sound like the chipmunks.
Hmmm yeah. Keep in mind that if you have two channels you'll probably need to either select one channel or read from both, I suppose.

If you can wait a bit (two days or so) I can make it more flexible.

Also, the 1 you are changing to 2 is the sample width.
Code:
Wave_write.setparams(tuple)
    The tuple should be (nchannels, sampwidth, framerate, nframes, comptype, compname), with values valid for the set*() methods. Sets all parameters.

Last edited by Wizzup?; 07-28-2010 at 09:15 AM.
Reply With Quote
(#14)
Old
moser moser is offline
Registered User
Chicken
moser is on a distinguished road
 
Activity Longevity
1/20 1/20
Today Posts
0/5 ssssssss5
Default 07-28-2010, 04:02 PM

Thanks for responding. I understand what the 2 did. But I don't understand why changing to 16 bits/sample causes the recorded audio to go garbled. I also don't understand how to increase the sample rate. Frankly I also don't understand were arecord fits into this! Oh well, I will wait until you make more changes. Thanks very much!
Reply With Quote
(#15)
Old
Wizzup?'s Avatar
Wizzup? Wizzup? is offline
Administrator
SRL Old Timer SRL DonatorSRL ScripterSRL DeveloperAdministrator
Corporeal Beast
Wizzup? has disabled reputation
 
Activity Longevity
18/20 20/20
Today Posts
0/5 sssss9649
Send a message via ICQ to Wizzup?
Default 07-31-2010, 10:47 PM

Well if I decide to work on this any time soon, you can always find the latest version here: http://git.wizzup.org/?p=vacr.git;a=summary

For now, it would probably be easier to specify a sample rate of 8000 in arecord. (Just pass "-r 8000" as second argument)

eg:
python Code:
p = subprocess.Popen(['arecord', '-r 8000'], stdout=subprocess.PIPE)
Reply With Quote
(#16)
Old
moser moser is offline
Registered User
Chicken
moser is on a distinguished road
 
Activity Longevity
1/20 1/20
Today Posts
0/5 ssssssss5
Default 08-01-2010, 05:15 PM

Thanks very much. I will follow this at your repo.

How does one change the number of bits per sample? Right now it records using unsigned 8 bit, what would I do to change this to signed 16 bit? Putting -f S16_LE in the arecord line just causes an error like this:

Code:
arecord: main:495: wrong extended format ' S16_LE'
Reply With Quote
(#17)
Old
Wizzup?'s Avatar
Wizzup? Wizzup? is offline
Administrator
SRL Old Timer SRL DonatorSRL ScripterSRL DeveloperAdministrator
Corporeal Beast
Wizzup? has disabled reputation
 
Activity Longevity
18/20 20/20
Today Posts
0/5 sssss9649
Send a message via ICQ to Wizzup?
Default 08-01-2010, 07:12 PM

Quote:
Originally Posted by moser View Post
Thanks very much. I will follow this at your repo.

How does one change the number of bits per sample? Right now it records using unsigned 8 bit, what would I do to change this to signed 16 bit? Putting -f S16_LE in the arecord line just causes an error like this:

Code:
arecord: main:495: wrong extended format ' S16_LE'
I was thinking about -s 16000. (Try arecord -s 16000 > test.wav) Ctrl+C it after a few seconds, and then play it with something that shows the rate.

Last edited by Wizzup?; 08-01-2010 at 07:19 PM.
Reply With Quote
(#18)
Old
moser moser is offline
Registered User
Chicken
moser is on a distinguished road
 
Activity Longevity
1/20 1/20
Today Posts
0/5 ssssssss5
Default 08-02-2010, 01:13 PM

Yes, changing the sampling rate works fine, I also changed the number in the 2 other places in the script so the processing would make sense. But what about the bits/sample issue? I can't seem to pass that info to arecord, nor change it on the python line.
Reply With Quote
(#19)
Old
Wizzup?'s Avatar
Wizzup? Wizzup? is offline
Administrator
SRL Old Timer SRL DonatorSRL ScripterSRL DeveloperAdministrator
Corporeal Beast
Wizzup? has disabled reputation
 
Activity Longevity
18/20 20/20
Today Posts
0/5 sssss9649
Send a message via ICQ to Wizzup?
Default 08-27-2010, 07:39 PM

I'll get to this in a bit...
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump



Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
vBulletin Skin developed by: vBStyles.com