Ruby 操作二进制文件,wav与pcm文件转换

背景及功能介绍

今天有一个任务是分割wav成pcm文件,以及把pcm加上头成为wav文件。因为部分功能有现成的C语言程序,所以就用C语言做了。

当我对wav文件格式了解后突然发现完全可以用ruby来实现这些操作,正好自己对ruby操作二进制文件有些疑惑(这个疑惑原来使用Array#pack解决),于是就重写今天主要实现的功能。

程序实现如下,希望对做语音的同学有些帮助:
# -*- coding:utf-8 -*-
# 格式参考 http://blog.csdn.net/zhihu008/article/details/7854529
# C程序参考 http://blog.csdn.net/gavinr/article/details/6957136
# ruby pack 参考 http://blog.csdn.net/dazhi_100/article/details/11787177
class WAV_aux
    def initialize(channels = 1,bits = 16,sample_rate = 8000)
        @channels=channels
        @bits=bits
        @sample_rate=sample_rate; #毫秒
    end
    def seg_wav(f_wav_name,f_pcm_name,bg,ed)
        # 毫秒
        mul=@sample_rate/1000
        mul*=2 # 2个字节
        File.open f_pcm_name,"wb" do |w|
        File.open f_wav_name,"rb" do |f|
            f.seek( 44 +  bg*mul)
            w.syswrite( f.sysread( (ed-bg+1)*mul ) )
        end
        end
    end
    def add_pcm_head(f_wav_name,f_pcm_name)
        pcmHEADER=Array.new(3)
        pcmFMT=Array.new(8)
        pcmDATA=Array.new(2)
        pcmHEADER[0]="RIFF"
        pcmHEADER[1]=44 # +pcm长度 现在未知
        pcmHEADER[2]="WAVE"

        pcmFMT[0]="fmt "
        pcmFMT[1]=[16].pack("L")
        pcmFMT[2]=[1].pack("S")
        pcmFMT[3]=[@channels].pack("S")
        pcmFMT[4]=[@sample_rate].pack("L")
        pcmFMT[5]=[@sample_rate * 2 ].pack("L") # 2表示每个采样点占2个字节
        pcmFMT[6]=[2].pack("S")
        pcmFMT[7]=[@bits].pack("S")

        pcmDATA[0]="data"
        pcmDATA[1]=0  
        data=""
        File.open f_pcm_name,"rb" do |f|
            pcmDATA[1]=f.size
            data=f.sysread(pcmDATA[1])
        end
        pcmHEADER[1]+=pcmDATA[1]
        pcmHEADER[1]=[pcmHEADER[1]].pack("L")
        pcmDATA[1]=[pcmDATA[1]].pack("L")
        File.open f_wav_name,"wb+" do |w|
            pcmHEADER.each do |x|
                w.syswrite(x)
            end
            pcmFMT.each do |x|
                w.syswrite(x)
            end
            pcmDATA.each do |x|
                w.syswrite(x)
            end
            w.syswrite(data)
        end
            #w.syswrite( "RIFF" ) 只有字符串直接可以
            #p [1000].pack("L") #能显示就显示字符,否则就 \x
            #w.seek( 4 , IO::SEEK_CUR) # 可以直接空开文件
            #w.syswrite( [10,22].pack("LC") )
            #w.syswrite( [1000].pack("L") )
    end #add_pcm_head
end #Class
para=["28919.wav","lx.pcm",2000,20000]
wav_aux=WAV_aux.new
#wav_aux.seg_wav(*para)
para=["lx.wav","lx.pcm"]
wav_aux.add_pcm_head(*para)

  • ruby的Array有个sample方法可以随机选取指定数目的数组内容且不重复。
  • 第一次用markdown写,感觉不好用(预览正常最后显示不正常)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值