Python - downsampling wav audio file












5















I have to downsample a wav file from 44100Hz to 16000Hz without using any external python libraries, so preferably wave and/or audioop. I tried just changing the wav files framerate to 16000 by using setframerate function but that just slows down the entire recording. How can I just downsample the audio file to 16kHz and maintain the same length of the audio?



Thank you very much in advance










share|improve this question























  • If you go down to 11025Hz it will be easier, just low pass filter and then take every 4th sample

    – samgak
    Jun 3 '15 at 12:22











  • Is audioop's ratecv what you're after? docs.python.org/2/library/audioop.html#audioop.ratecv

    – Jim Jeffries
    Jun 3 '15 at 12:23











  • It needs to be 16kHz because our pipeline tool needs to export it for Unity projects. Would you mind giving me an example of using the audioop.ratecv function? Because I'm confused with the fragment parameter of that function. How do I get it? @JimJeffries

    – d3cr1pt0r
    Jun 3 '15 at 12:33


















5















I have to downsample a wav file from 44100Hz to 16000Hz without using any external python libraries, so preferably wave and/or audioop. I tried just changing the wav files framerate to 16000 by using setframerate function but that just slows down the entire recording. How can I just downsample the audio file to 16kHz and maintain the same length of the audio?



Thank you very much in advance










share|improve this question























  • If you go down to 11025Hz it will be easier, just low pass filter and then take every 4th sample

    – samgak
    Jun 3 '15 at 12:22











  • Is audioop's ratecv what you're after? docs.python.org/2/library/audioop.html#audioop.ratecv

    – Jim Jeffries
    Jun 3 '15 at 12:23











  • It needs to be 16kHz because our pipeline tool needs to export it for Unity projects. Would you mind giving me an example of using the audioop.ratecv function? Because I'm confused with the fragment parameter of that function. How do I get it? @JimJeffries

    – d3cr1pt0r
    Jun 3 '15 at 12:33
















5












5








5


6






I have to downsample a wav file from 44100Hz to 16000Hz without using any external python libraries, so preferably wave and/or audioop. I tried just changing the wav files framerate to 16000 by using setframerate function but that just slows down the entire recording. How can I just downsample the audio file to 16kHz and maintain the same length of the audio?



Thank you very much in advance










share|improve this question














I have to downsample a wav file from 44100Hz to 16000Hz without using any external python libraries, so preferably wave and/or audioop. I tried just changing the wav files framerate to 16000 by using setframerate function but that just slows down the entire recording. How can I just downsample the audio file to 16kHz and maintain the same length of the audio?



Thank you very much in advance







python audio wav wave downsampling






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jun 3 '15 at 12:10









d3cr1pt0rd3cr1pt0r

71117




71117













  • If you go down to 11025Hz it will be easier, just low pass filter and then take every 4th sample

    – samgak
    Jun 3 '15 at 12:22











  • Is audioop's ratecv what you're after? docs.python.org/2/library/audioop.html#audioop.ratecv

    – Jim Jeffries
    Jun 3 '15 at 12:23











  • It needs to be 16kHz because our pipeline tool needs to export it for Unity projects. Would you mind giving me an example of using the audioop.ratecv function? Because I'm confused with the fragment parameter of that function. How do I get it? @JimJeffries

    – d3cr1pt0r
    Jun 3 '15 at 12:33





















  • If you go down to 11025Hz it will be easier, just low pass filter and then take every 4th sample

    – samgak
    Jun 3 '15 at 12:22











  • Is audioop's ratecv what you're after? docs.python.org/2/library/audioop.html#audioop.ratecv

    – Jim Jeffries
    Jun 3 '15 at 12:23











  • It needs to be 16kHz because our pipeline tool needs to export it for Unity projects. Would you mind giving me an example of using the audioop.ratecv function? Because I'm confused with the fragment parameter of that function. How do I get it? @JimJeffries

    – d3cr1pt0r
    Jun 3 '15 at 12:33



















If you go down to 11025Hz it will be easier, just low pass filter and then take every 4th sample

– samgak
Jun 3 '15 at 12:22





If you go down to 11025Hz it will be easier, just low pass filter and then take every 4th sample

– samgak
Jun 3 '15 at 12:22













Is audioop's ratecv what you're after? docs.python.org/2/library/audioop.html#audioop.ratecv

– Jim Jeffries
Jun 3 '15 at 12:23





Is audioop's ratecv what you're after? docs.python.org/2/library/audioop.html#audioop.ratecv

– Jim Jeffries
Jun 3 '15 at 12:23













It needs to be 16kHz because our pipeline tool needs to export it for Unity projects. Would you mind giving me an example of using the audioop.ratecv function? Because I'm confused with the fragment parameter of that function. How do I get it? @JimJeffries

– d3cr1pt0r
Jun 3 '15 at 12:33







It needs to be 16kHz because our pipeline tool needs to export it for Unity projects. Would you mind giving me an example of using the audioop.ratecv function? Because I'm confused with the fragment parameter of that function. How do I get it? @JimJeffries

– d3cr1pt0r
Jun 3 '15 at 12:33














3 Answers
3






active

oldest

votes


















4














You can use Librosa's load() function,



import librosa    
y, s = librosa.load('test.wav', sr=8000) # Downsample 44.1kHz to 8kHz


The extra effort to install Librosa is probably worth the peace of mind.



Pro-tip: when installing Librosa on Anaconda, you need to install ffmpeg as well, so



pip install librosa
conda install -c conda-forge ffmpeg


This saves you the NoBackendError() error.






share|improve this answer
























  • Probably the best comment here, and seems most up to date as well. Just lacking the save that OP requested, which is as simple as librosa.output.write_wav(filename, y, sr).

    – hyit
    Jun 29 '18 at 12:11





















3














Thank you all for your answers. I found a solution already and it works very nice. Here is the whole function.



def downsampleWav(src, dst, inrate=44100, outrate=16000, inchannels=2, outchannels=1):
if not os.path.exists(src):
print 'Source not found!'
return False

if not os.path.exists(os.path.dirname(dst)):
os.makedirs(os.path.dirname(dst))

try:
s_read = wave.open(src, 'r')
s_write = wave.open(dst, 'w')
except:
print 'Failed to open files!'
return False

n_frames = s_read.getnframes()
data = s_read.readframes(n_frames)

try:
converted = audioop.ratecv(data, 2, inchannels, inrate, outrate, None)
if outchannels == 1:
converted = audioop.tomono(converted[0], 2, 1, 0)
except:
print 'Failed to downsample wav'
return False

try:
s_write.setparams((outchannels, 2, outrate, 0, 'NONE', 'Uncompressed'))
s_write.writeframes(converted)
except:
print 'Failed to write wav'
return False

try:
s_read.close()
s_write.close()
except:
print 'Failed to close wav files'
return False

return True





share|improve this answer



















  • 2





    I know this is old but I just had the same problem so I tried the code and I think it has a subtle bug. If my inchannels=1 and outchannels=1 the tomono function will be called anyway which messes up my audio signal (the length gets cut in half). Also when writing the frames, shouldn't you only write converted[0] (depending if tomono was called obviously) because the newstate returned by ratecv is irrelevant?

    – user667804
    Feb 10 '16 at 15:41











  • The above modules are all in the std lib

    – spacether
    May 3 '18 at 0:59



















2














You can use resample in scipy. It's a bit of a headache to do, because there's some type conversion to be done between the bytestring native to python and the arrays needed in scipy. There's another headache, because in the wave module in Python, there is no way to tell if the data is signed or not (only if it's 8 or 16 bits). It might (should) work for both, but I haven't tested it.



Here's a small program which converts (unsigned) 8 and 16 bits mono from 44.1 to 16. If you have stereo, or use other formats, it shouldn't be that difficult to adapt. Edit the input/output names at the start of the code. Never got around to use the command line arguments.



#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# downsample.py
#
# Copyright 2015 John Coppens <john@jcoppens.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA.
#
#

inwave = "sine_44k.wav"
outwave = "sine_16k.wav"

import wave
import numpy as np
import scipy.signal as sps

class DownSample():
def __init__(self):
self.in_rate = 44100.0
self.out_rate = 16000.0

def open_file(self, fname):
try:
self.in_wav = wave.open(fname)
except:
print("Cannot open wav file (%s)" % fname)
return False

if self.in_wav.getframerate() != self.in_rate:
print("Frame rate is not %d (it's %d)" %
(self.in_rate, self.in_wav.getframerate()))
return False

self.in_nframes = self.in_wav.getnframes()
print("Frames: %d" % self.in_wav.getnframes())

if self.in_wav.getsampwidth() == 1:
self.nptype = np.uint8
elif self.in_wav.getsampwidth() == 2:
self.nptype = np.uint16

return True

def resample(self, fname):
self.out_wav = wave.open(fname, "w")
self.out_wav.setframerate(self.out_rate)
self.out_wav.setnchannels(self.in_wav.getnchannels())
self.out_wav.setsampwidth (self.in_wav.getsampwidth())
self.out_wav.setnframes(1)

print("Nr output channels: %d" % self.out_wav.getnchannels())

audio = self.in_wav.readframes(self.in_nframes)
nroutsamples = round(len(audio) * self.out_rate/self.in_rate)
print("Nr output samples: %d" % nroutsamples)

audio_out = sps.resample(np.fromstring(audio, self.nptype), nroutsamples)
audio_out = audio_out.astype(self.nptype)

self.out_wav.writeframes(audio_out.copy(order='C'))

self.out_wav.close()

def main():
ds = DownSample()
if not ds.open_file(inwave): return 1
ds.resample(outwave)
return 0

if __name__ == '__main__':
main()





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f30619740%2fpython-downsampling-wav-audio-file%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    4














    You can use Librosa's load() function,



    import librosa    
    y, s = librosa.load('test.wav', sr=8000) # Downsample 44.1kHz to 8kHz


    The extra effort to install Librosa is probably worth the peace of mind.



    Pro-tip: when installing Librosa on Anaconda, you need to install ffmpeg as well, so



    pip install librosa
    conda install -c conda-forge ffmpeg


    This saves you the NoBackendError() error.






    share|improve this answer
























    • Probably the best comment here, and seems most up to date as well. Just lacking the save that OP requested, which is as simple as librosa.output.write_wav(filename, y, sr).

      – hyit
      Jun 29 '18 at 12:11


















    4














    You can use Librosa's load() function,



    import librosa    
    y, s = librosa.load('test.wav', sr=8000) # Downsample 44.1kHz to 8kHz


    The extra effort to install Librosa is probably worth the peace of mind.



    Pro-tip: when installing Librosa on Anaconda, you need to install ffmpeg as well, so



    pip install librosa
    conda install -c conda-forge ffmpeg


    This saves you the NoBackendError() error.






    share|improve this answer
























    • Probably the best comment here, and seems most up to date as well. Just lacking the save that OP requested, which is as simple as librosa.output.write_wav(filename, y, sr).

      – hyit
      Jun 29 '18 at 12:11
















    4












    4








    4







    You can use Librosa's load() function,



    import librosa    
    y, s = librosa.load('test.wav', sr=8000) # Downsample 44.1kHz to 8kHz


    The extra effort to install Librosa is probably worth the peace of mind.



    Pro-tip: when installing Librosa on Anaconda, you need to install ffmpeg as well, so



    pip install librosa
    conda install -c conda-forge ffmpeg


    This saves you the NoBackendError() error.






    share|improve this answer













    You can use Librosa's load() function,



    import librosa    
    y, s = librosa.load('test.wav', sr=8000) # Downsample 44.1kHz to 8kHz


    The extra effort to install Librosa is probably worth the peace of mind.



    Pro-tip: when installing Librosa on Anaconda, you need to install ffmpeg as well, so



    pip install librosa
    conda install -c conda-forge ffmpeg


    This saves you the NoBackendError() error.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Mar 18 '18 at 12:31









    wafflecatwafflecat

    39838




    39838













    • Probably the best comment here, and seems most up to date as well. Just lacking the save that OP requested, which is as simple as librosa.output.write_wav(filename, y, sr).

      – hyit
      Jun 29 '18 at 12:11





















    • Probably the best comment here, and seems most up to date as well. Just lacking the save that OP requested, which is as simple as librosa.output.write_wav(filename, y, sr).

      – hyit
      Jun 29 '18 at 12:11



















    Probably the best comment here, and seems most up to date as well. Just lacking the save that OP requested, which is as simple as librosa.output.write_wav(filename, y, sr).

    – hyit
    Jun 29 '18 at 12:11







    Probably the best comment here, and seems most up to date as well. Just lacking the save that OP requested, which is as simple as librosa.output.write_wav(filename, y, sr).

    – hyit
    Jun 29 '18 at 12:11















    3














    Thank you all for your answers. I found a solution already and it works very nice. Here is the whole function.



    def downsampleWav(src, dst, inrate=44100, outrate=16000, inchannels=2, outchannels=1):
    if not os.path.exists(src):
    print 'Source not found!'
    return False

    if not os.path.exists(os.path.dirname(dst)):
    os.makedirs(os.path.dirname(dst))

    try:
    s_read = wave.open(src, 'r')
    s_write = wave.open(dst, 'w')
    except:
    print 'Failed to open files!'
    return False

    n_frames = s_read.getnframes()
    data = s_read.readframes(n_frames)

    try:
    converted = audioop.ratecv(data, 2, inchannels, inrate, outrate, None)
    if outchannels == 1:
    converted = audioop.tomono(converted[0], 2, 1, 0)
    except:
    print 'Failed to downsample wav'
    return False

    try:
    s_write.setparams((outchannels, 2, outrate, 0, 'NONE', 'Uncompressed'))
    s_write.writeframes(converted)
    except:
    print 'Failed to write wav'
    return False

    try:
    s_read.close()
    s_write.close()
    except:
    print 'Failed to close wav files'
    return False

    return True





    share|improve this answer



















    • 2





      I know this is old but I just had the same problem so I tried the code and I think it has a subtle bug. If my inchannels=1 and outchannels=1 the tomono function will be called anyway which messes up my audio signal (the length gets cut in half). Also when writing the frames, shouldn't you only write converted[0] (depending if tomono was called obviously) because the newstate returned by ratecv is irrelevant?

      – user667804
      Feb 10 '16 at 15:41











    • The above modules are all in the std lib

      – spacether
      May 3 '18 at 0:59
















    3














    Thank you all for your answers. I found a solution already and it works very nice. Here is the whole function.



    def downsampleWav(src, dst, inrate=44100, outrate=16000, inchannels=2, outchannels=1):
    if not os.path.exists(src):
    print 'Source not found!'
    return False

    if not os.path.exists(os.path.dirname(dst)):
    os.makedirs(os.path.dirname(dst))

    try:
    s_read = wave.open(src, 'r')
    s_write = wave.open(dst, 'w')
    except:
    print 'Failed to open files!'
    return False

    n_frames = s_read.getnframes()
    data = s_read.readframes(n_frames)

    try:
    converted = audioop.ratecv(data, 2, inchannels, inrate, outrate, None)
    if outchannels == 1:
    converted = audioop.tomono(converted[0], 2, 1, 0)
    except:
    print 'Failed to downsample wav'
    return False

    try:
    s_write.setparams((outchannels, 2, outrate, 0, 'NONE', 'Uncompressed'))
    s_write.writeframes(converted)
    except:
    print 'Failed to write wav'
    return False

    try:
    s_read.close()
    s_write.close()
    except:
    print 'Failed to close wav files'
    return False

    return True





    share|improve this answer



















    • 2





      I know this is old but I just had the same problem so I tried the code and I think it has a subtle bug. If my inchannels=1 and outchannels=1 the tomono function will be called anyway which messes up my audio signal (the length gets cut in half). Also when writing the frames, shouldn't you only write converted[0] (depending if tomono was called obviously) because the newstate returned by ratecv is irrelevant?

      – user667804
      Feb 10 '16 at 15:41











    • The above modules are all in the std lib

      – spacether
      May 3 '18 at 0:59














    3












    3








    3







    Thank you all for your answers. I found a solution already and it works very nice. Here is the whole function.



    def downsampleWav(src, dst, inrate=44100, outrate=16000, inchannels=2, outchannels=1):
    if not os.path.exists(src):
    print 'Source not found!'
    return False

    if not os.path.exists(os.path.dirname(dst)):
    os.makedirs(os.path.dirname(dst))

    try:
    s_read = wave.open(src, 'r')
    s_write = wave.open(dst, 'w')
    except:
    print 'Failed to open files!'
    return False

    n_frames = s_read.getnframes()
    data = s_read.readframes(n_frames)

    try:
    converted = audioop.ratecv(data, 2, inchannels, inrate, outrate, None)
    if outchannels == 1:
    converted = audioop.tomono(converted[0], 2, 1, 0)
    except:
    print 'Failed to downsample wav'
    return False

    try:
    s_write.setparams((outchannels, 2, outrate, 0, 'NONE', 'Uncompressed'))
    s_write.writeframes(converted)
    except:
    print 'Failed to write wav'
    return False

    try:
    s_read.close()
    s_write.close()
    except:
    print 'Failed to close wav files'
    return False

    return True





    share|improve this answer













    Thank you all for your answers. I found a solution already and it works very nice. Here is the whole function.



    def downsampleWav(src, dst, inrate=44100, outrate=16000, inchannels=2, outchannels=1):
    if not os.path.exists(src):
    print 'Source not found!'
    return False

    if not os.path.exists(os.path.dirname(dst)):
    os.makedirs(os.path.dirname(dst))

    try:
    s_read = wave.open(src, 'r')
    s_write = wave.open(dst, 'w')
    except:
    print 'Failed to open files!'
    return False

    n_frames = s_read.getnframes()
    data = s_read.readframes(n_frames)

    try:
    converted = audioop.ratecv(data, 2, inchannels, inrate, outrate, None)
    if outchannels == 1:
    converted = audioop.tomono(converted[0], 2, 1, 0)
    except:
    print 'Failed to downsample wav'
    return False

    try:
    s_write.setparams((outchannels, 2, outrate, 0, 'NONE', 'Uncompressed'))
    s_write.writeframes(converted)
    except:
    print 'Failed to write wav'
    return False

    try:
    s_read.close()
    s_write.close()
    except:
    print 'Failed to close wav files'
    return False

    return True






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jun 5 '15 at 7:29









    d3cr1pt0rd3cr1pt0r

    71117




    71117








    • 2





      I know this is old but I just had the same problem so I tried the code and I think it has a subtle bug. If my inchannels=1 and outchannels=1 the tomono function will be called anyway which messes up my audio signal (the length gets cut in half). Also when writing the frames, shouldn't you only write converted[0] (depending if tomono was called obviously) because the newstate returned by ratecv is irrelevant?

      – user667804
      Feb 10 '16 at 15:41











    • The above modules are all in the std lib

      – spacether
      May 3 '18 at 0:59














    • 2





      I know this is old but I just had the same problem so I tried the code and I think it has a subtle bug. If my inchannels=1 and outchannels=1 the tomono function will be called anyway which messes up my audio signal (the length gets cut in half). Also when writing the frames, shouldn't you only write converted[0] (depending if tomono was called obviously) because the newstate returned by ratecv is irrelevant?

      – user667804
      Feb 10 '16 at 15:41











    • The above modules are all in the std lib

      – spacether
      May 3 '18 at 0:59








    2




    2





    I know this is old but I just had the same problem so I tried the code and I think it has a subtle bug. If my inchannels=1 and outchannels=1 the tomono function will be called anyway which messes up my audio signal (the length gets cut in half). Also when writing the frames, shouldn't you only write converted[0] (depending if tomono was called obviously) because the newstate returned by ratecv is irrelevant?

    – user667804
    Feb 10 '16 at 15:41





    I know this is old but I just had the same problem so I tried the code and I think it has a subtle bug. If my inchannels=1 and outchannels=1 the tomono function will be called anyway which messes up my audio signal (the length gets cut in half). Also when writing the frames, shouldn't you only write converted[0] (depending if tomono was called obviously) because the newstate returned by ratecv is irrelevant?

    – user667804
    Feb 10 '16 at 15:41













    The above modules are all in the std lib

    – spacether
    May 3 '18 at 0:59





    The above modules are all in the std lib

    – spacether
    May 3 '18 at 0:59











    2














    You can use resample in scipy. It's a bit of a headache to do, because there's some type conversion to be done between the bytestring native to python and the arrays needed in scipy. There's another headache, because in the wave module in Python, there is no way to tell if the data is signed or not (only if it's 8 or 16 bits). It might (should) work for both, but I haven't tested it.



    Here's a small program which converts (unsigned) 8 and 16 bits mono from 44.1 to 16. If you have stereo, or use other formats, it shouldn't be that difficult to adapt. Edit the input/output names at the start of the code. Never got around to use the command line arguments.



    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #
    # downsample.py
    #
    # Copyright 2015 John Coppens <john@jcoppens.com>
    #
    # This program is free software; you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation; either version 2 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
    # MA 02110-1301, USA.
    #
    #

    inwave = "sine_44k.wav"
    outwave = "sine_16k.wav"

    import wave
    import numpy as np
    import scipy.signal as sps

    class DownSample():
    def __init__(self):
    self.in_rate = 44100.0
    self.out_rate = 16000.0

    def open_file(self, fname):
    try:
    self.in_wav = wave.open(fname)
    except:
    print("Cannot open wav file (%s)" % fname)
    return False

    if self.in_wav.getframerate() != self.in_rate:
    print("Frame rate is not %d (it's %d)" %
    (self.in_rate, self.in_wav.getframerate()))
    return False

    self.in_nframes = self.in_wav.getnframes()
    print("Frames: %d" % self.in_wav.getnframes())

    if self.in_wav.getsampwidth() == 1:
    self.nptype = np.uint8
    elif self.in_wav.getsampwidth() == 2:
    self.nptype = np.uint16

    return True

    def resample(self, fname):
    self.out_wav = wave.open(fname, "w")
    self.out_wav.setframerate(self.out_rate)
    self.out_wav.setnchannels(self.in_wav.getnchannels())
    self.out_wav.setsampwidth (self.in_wav.getsampwidth())
    self.out_wav.setnframes(1)

    print("Nr output channels: %d" % self.out_wav.getnchannels())

    audio = self.in_wav.readframes(self.in_nframes)
    nroutsamples = round(len(audio) * self.out_rate/self.in_rate)
    print("Nr output samples: %d" % nroutsamples)

    audio_out = sps.resample(np.fromstring(audio, self.nptype), nroutsamples)
    audio_out = audio_out.astype(self.nptype)

    self.out_wav.writeframes(audio_out.copy(order='C'))

    self.out_wav.close()

    def main():
    ds = DownSample()
    if not ds.open_file(inwave): return 1
    ds.resample(outwave)
    return 0

    if __name__ == '__main__':
    main()





    share|improve this answer




























      2














      You can use resample in scipy. It's a bit of a headache to do, because there's some type conversion to be done between the bytestring native to python and the arrays needed in scipy. There's another headache, because in the wave module in Python, there is no way to tell if the data is signed or not (only if it's 8 or 16 bits). It might (should) work for both, but I haven't tested it.



      Here's a small program which converts (unsigned) 8 and 16 bits mono from 44.1 to 16. If you have stereo, or use other formats, it shouldn't be that difficult to adapt. Edit the input/output names at the start of the code. Never got around to use the command line arguments.



      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
      #
      # downsample.py
      #
      # Copyright 2015 John Coppens <john@jcoppens.com>
      #
      # This program is free software; you can redistribute it and/or modify
      # it under the terms of the GNU General Public License as published by
      # the Free Software Foundation; either version 2 of the License, or
      # (at your option) any later version.
      #
      # This program is distributed in the hope that it will be useful,
      # but WITHOUT ANY WARRANTY; without even the implied warranty of
      # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      # GNU General Public License for more details.
      #
      # You should have received a copy of the GNU General Public License
      # along with this program; if not, write to the Free Software
      # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      # MA 02110-1301, USA.
      #
      #

      inwave = "sine_44k.wav"
      outwave = "sine_16k.wav"

      import wave
      import numpy as np
      import scipy.signal as sps

      class DownSample():
      def __init__(self):
      self.in_rate = 44100.0
      self.out_rate = 16000.0

      def open_file(self, fname):
      try:
      self.in_wav = wave.open(fname)
      except:
      print("Cannot open wav file (%s)" % fname)
      return False

      if self.in_wav.getframerate() != self.in_rate:
      print("Frame rate is not %d (it's %d)" %
      (self.in_rate, self.in_wav.getframerate()))
      return False

      self.in_nframes = self.in_wav.getnframes()
      print("Frames: %d" % self.in_wav.getnframes())

      if self.in_wav.getsampwidth() == 1:
      self.nptype = np.uint8
      elif self.in_wav.getsampwidth() == 2:
      self.nptype = np.uint16

      return True

      def resample(self, fname):
      self.out_wav = wave.open(fname, "w")
      self.out_wav.setframerate(self.out_rate)
      self.out_wav.setnchannels(self.in_wav.getnchannels())
      self.out_wav.setsampwidth (self.in_wav.getsampwidth())
      self.out_wav.setnframes(1)

      print("Nr output channels: %d" % self.out_wav.getnchannels())

      audio = self.in_wav.readframes(self.in_nframes)
      nroutsamples = round(len(audio) * self.out_rate/self.in_rate)
      print("Nr output samples: %d" % nroutsamples)

      audio_out = sps.resample(np.fromstring(audio, self.nptype), nroutsamples)
      audio_out = audio_out.astype(self.nptype)

      self.out_wav.writeframes(audio_out.copy(order='C'))

      self.out_wav.close()

      def main():
      ds = DownSample()
      if not ds.open_file(inwave): return 1
      ds.resample(outwave)
      return 0

      if __name__ == '__main__':
      main()





      share|improve this answer


























        2












        2








        2







        You can use resample in scipy. It's a bit of a headache to do, because there's some type conversion to be done between the bytestring native to python and the arrays needed in scipy. There's another headache, because in the wave module in Python, there is no way to tell if the data is signed or not (only if it's 8 or 16 bits). It might (should) work for both, but I haven't tested it.



        Here's a small program which converts (unsigned) 8 and 16 bits mono from 44.1 to 16. If you have stereo, or use other formats, it shouldn't be that difficult to adapt. Edit the input/output names at the start of the code. Never got around to use the command line arguments.



        #!/usr/bin/env python
        # -*- coding: utf-8 -*-
        #
        # downsample.py
        #
        # Copyright 2015 John Coppens <john@jcoppens.com>
        #
        # This program is free software; you can redistribute it and/or modify
        # it under the terms of the GNU General Public License as published by
        # the Free Software Foundation; either version 2 of the License, or
        # (at your option) any later version.
        #
        # This program is distributed in the hope that it will be useful,
        # but WITHOUT ANY WARRANTY; without even the implied warranty of
        # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
        # GNU General Public License for more details.
        #
        # You should have received a copy of the GNU General Public License
        # along with this program; if not, write to the Free Software
        # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
        # MA 02110-1301, USA.
        #
        #

        inwave = "sine_44k.wav"
        outwave = "sine_16k.wav"

        import wave
        import numpy as np
        import scipy.signal as sps

        class DownSample():
        def __init__(self):
        self.in_rate = 44100.0
        self.out_rate = 16000.0

        def open_file(self, fname):
        try:
        self.in_wav = wave.open(fname)
        except:
        print("Cannot open wav file (%s)" % fname)
        return False

        if self.in_wav.getframerate() != self.in_rate:
        print("Frame rate is not %d (it's %d)" %
        (self.in_rate, self.in_wav.getframerate()))
        return False

        self.in_nframes = self.in_wav.getnframes()
        print("Frames: %d" % self.in_wav.getnframes())

        if self.in_wav.getsampwidth() == 1:
        self.nptype = np.uint8
        elif self.in_wav.getsampwidth() == 2:
        self.nptype = np.uint16

        return True

        def resample(self, fname):
        self.out_wav = wave.open(fname, "w")
        self.out_wav.setframerate(self.out_rate)
        self.out_wav.setnchannels(self.in_wav.getnchannels())
        self.out_wav.setsampwidth (self.in_wav.getsampwidth())
        self.out_wav.setnframes(1)

        print("Nr output channels: %d" % self.out_wav.getnchannels())

        audio = self.in_wav.readframes(self.in_nframes)
        nroutsamples = round(len(audio) * self.out_rate/self.in_rate)
        print("Nr output samples: %d" % nroutsamples)

        audio_out = sps.resample(np.fromstring(audio, self.nptype), nroutsamples)
        audio_out = audio_out.astype(self.nptype)

        self.out_wav.writeframes(audio_out.copy(order='C'))

        self.out_wav.close()

        def main():
        ds = DownSample()
        if not ds.open_file(inwave): return 1
        ds.resample(outwave)
        return 0

        if __name__ == '__main__':
        main()





        share|improve this answer













        You can use resample in scipy. It's a bit of a headache to do, because there's some type conversion to be done between the bytestring native to python and the arrays needed in scipy. There's another headache, because in the wave module in Python, there is no way to tell if the data is signed or not (only if it's 8 or 16 bits). It might (should) work for both, but I haven't tested it.



        Here's a small program which converts (unsigned) 8 and 16 bits mono from 44.1 to 16. If you have stereo, or use other formats, it shouldn't be that difficult to adapt. Edit the input/output names at the start of the code. Never got around to use the command line arguments.



        #!/usr/bin/env python
        # -*- coding: utf-8 -*-
        #
        # downsample.py
        #
        # Copyright 2015 John Coppens <john@jcoppens.com>
        #
        # This program is free software; you can redistribute it and/or modify
        # it under the terms of the GNU General Public License as published by
        # the Free Software Foundation; either version 2 of the License, or
        # (at your option) any later version.
        #
        # This program is distributed in the hope that it will be useful,
        # but WITHOUT ANY WARRANTY; without even the implied warranty of
        # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
        # GNU General Public License for more details.
        #
        # You should have received a copy of the GNU General Public License
        # along with this program; if not, write to the Free Software
        # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
        # MA 02110-1301, USA.
        #
        #

        inwave = "sine_44k.wav"
        outwave = "sine_16k.wav"

        import wave
        import numpy as np
        import scipy.signal as sps

        class DownSample():
        def __init__(self):
        self.in_rate = 44100.0
        self.out_rate = 16000.0

        def open_file(self, fname):
        try:
        self.in_wav = wave.open(fname)
        except:
        print("Cannot open wav file (%s)" % fname)
        return False

        if self.in_wav.getframerate() != self.in_rate:
        print("Frame rate is not %d (it's %d)" %
        (self.in_rate, self.in_wav.getframerate()))
        return False

        self.in_nframes = self.in_wav.getnframes()
        print("Frames: %d" % self.in_wav.getnframes())

        if self.in_wav.getsampwidth() == 1:
        self.nptype = np.uint8
        elif self.in_wav.getsampwidth() == 2:
        self.nptype = np.uint16

        return True

        def resample(self, fname):
        self.out_wav = wave.open(fname, "w")
        self.out_wav.setframerate(self.out_rate)
        self.out_wav.setnchannels(self.in_wav.getnchannels())
        self.out_wav.setsampwidth (self.in_wav.getsampwidth())
        self.out_wav.setnframes(1)

        print("Nr output channels: %d" % self.out_wav.getnchannels())

        audio = self.in_wav.readframes(self.in_nframes)
        nroutsamples = round(len(audio) * self.out_rate/self.in_rate)
        print("Nr output samples: %d" % nroutsamples)

        audio_out = sps.resample(np.fromstring(audio, self.nptype), nroutsamples)
        audio_out = audio_out.astype(self.nptype)

        self.out_wav.writeframes(audio_out.copy(order='C'))

        self.out_wav.close()

        def main():
        ds = DownSample()
        if not ds.open_file(inwave): return 1
        ds.resample(outwave)
        return 0

        if __name__ == '__main__':
        main()






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jun 3 '15 at 19:09









        jcoppensjcoppens

        4,23241832




        4,23241832






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f30619740%2fpython-downsampling-wav-audio-file%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            404 Error Contact Form 7 ajax form submitting

            How to know if a Active Directory user can login interactively

            Refactoring coordinates for Minecraft Pi buildings written in Python