2012-02-06 26 views
11

Gần đây tôi đã chơi với ruby ​​và tôi đã quyết định bắt đầu một dự án đơn giản để viết một tập lệnh ruby ​​ghi lại âm thanh vào một tệp .wav. Tôi phát hiện ra rằng ruby ​​không cung cấp khả năng truy cập rất tốt vào các thiết bị phần cứng (và có lẽ nó không nên), nhưng PortAudio đó làm, và tôi phát hiện ra một wrapper tuyệt vời cho PA here (nó không phải là đá quý, tôi nghĩ bởi vì nó sử dụng ruby ffi để đính kèm vào PortAudio và thư viện PA có thể ở nhiều nơi). Tôi đã lúng túng thông qua tài liệu và ví dụ của PortAudio để tìm ra cách PA hoạt động. Tôi đã không viết hoặc đọc C trong nhiều năm.Sử dụng trình bao bọc PortAudio bằng ruby ​​để ghi âm .wav

Tôi đang gặp khó khăn với thông số nào tôi nên chuyển đến luồng trong khi tạo và bộ đệm trong khi tạo. Ví dụ: chính xác số frame là gì và nó có liên quan như thế nào với các thông số khác như channelsample rate. Tôi hoàn toàn mới để lập trình âm thanh nói chung là tốt, vì vậy nếu bất cứ ai có thể chỉ cho tôi một số hướng dẫn chung, vv, về âm thanh cấp thiết bị, tôi sẽ đánh giá cao nó.

ruby-portaudio cung cấp một ví dụ đơn lẻ tạo luồng và bộ đệm, viết wave sin vào bộ đệm, sau đó gửi bộ đệm đến luồng được phát. Một số ruby ​​tôi gặp rắc rối trong ví dụ, đặc biệt là khối vòng lặp.

PortAudio.init 

    block_size = 1024 
    sr = 44100 
    step = 1.0/sr 
    time = 0.0 

    stream = PortAudio::Stream.open(
      :sample_rate => sr, 
      :frames => block_size, 
      :output => { 
       :device => PortAudio::Device.default_output, 
       :channels => 1, 
       :sample_format => :float32 
       }) 

    buffer = PortAudio::SampleBuffer.new(
      :format => :float32, 
      :channels => 1, 
      :frames => block_size) 

    playing = true 
    Signal.trap('INT') { playing = false } 
    puts "Ctrl-C to exit" 

    stream.start 

    loop do 
    stream << buffer.fill { |frame, channel| 
     time += step 
     Math.cos(time * 2 * Math::PI * 440.0) * Math.cos(time * 2 * Math::PI) 
    } 

    break unless playing 
    end 

    stream.stop 

Nếu tôi định ghi, tôi nên đọc luồng vào bộ đệm, sau đó thao tác bộ đệm đó và ghi vào tệp, phải không?

Ngoài ra, nếu tôi sủa cây sai ở đây và có cách dễ dàng hơn để thực hiện việc này (trong ruby), một số hướng sẽ tốt đẹp.

+0

Dường như là một câu hỏi liên quan (không bị lừa đảo) ở đây http: // stackoverflow.com/questions/2716987/recording-audio-through-rtmp-rails –

Trả lời

3

Trước tiên, hãy làm rõ các cụm từ bạn đã hỏi. Với mục đích này tôi sẽ cố gắng giải thích đường ống âm thanh một cách đơn giản. Khi bạn tạo ra âm thanh như trong ví dụ của mình, thẻ âm thanh của bạn định kỳ yêu cầu các khung (= buffer = blocks) từ mã của bạn, mà bạn điền vào mẫu của bạn. Tỷ lệ lấy mẫu xác định số lượng mẫu bạn cung cấp trong vòng một giây và do đó tốc độ mà các mẫu của bạn được phát lại. Kích thước khung hình (= kích thước bộ đệm = kích thước khối) xác định số lượng mẫu bạn cung cấp trong một yêu cầu từ card âm thanh. Một bộ đệm thường khá nhỏ, vì kích thước bộ đệm ảnh hưởng trực tiếp đến độ trễ (bộ đệm lớn => độ trễ cao) và các mảng lớn có thể chậm (đặc biệt là các mảng ruby ​​chậm).

Những điều tương tự cũng xảy ra khi bạn đang ghi âm từ thẻ âm thanh của mình. Hàm của bạn được gọi là mọi lúc và sau đó, và các mẫu từ micrô thường được truyền vào như một đối số cho hàm (hoặc thậm chí chỉ là một tham chiếu đến bộ đệm như vậy). Sau đó, bạn sẽ được xử lý các mẫu này, ví dụ: bằng cách viết chúng vào đĩa.

Tôi biết rằng ý nghĩ "làm mọi thứ trong Ruby" khá hấp dẫn, bởi vì nó là một ngôn ngữ đẹp. Khi bạn đang lên kế hoạch xử lý âm thanh trong thời gian thực, tôi khuyên bạn nên chuyển sang ngôn ngữ được biên dịch (C, C++, Obj-C, ...). Chúng có thể xử lý âm thanh tốt hơn nhiều, bởi vì chúng gần gũi hơn với phần cứng hơn so với Ruby và do đó nói chung nhanh hơn, có thể khá là một vấn đề trong xử lý âm thanh. Đây có lẽ cũng là lý do tại sao có quá ít thư viện âm thanh Ruby xung quanh, vì vậy có lẽ Ruby không phải là công cụ phù hợp cho công việc.

Nhân tiện, tôi đã thử ruby-portaudio, ffi-portaudio cũng như âm thanh ruby ​​và không có thiết bị nào hoạt động bình thường trên Macbook của tôi (cố gắng tạo sóng sin). không có khả năng xử lý công cụ này (chưa?).

+0

Nếu bạn có thể gây rối với âm thanh thông qua một gui, bạn có thể gây rối với nó thông qua một ngôn ngữ kịch bản. Ví dụ: Dữ liệu thuần túy là ngôn ngữ lập trình đồ họa âm thanh vui nhộn, đủ chắc chắn, ít nhất một người đang cố gắng [lái xe bằng Ruby] (http://matschaffer.com/2010/11/ruby-midi-pure-data/). Tôi chắc rằng có những nỗ lực tương tự với [môi trường tổng hợp âm thanh khác] (http://en.wikipedia.org/wiki/Comparison_of_audio_synthesis_environments). – mgamba

+0

Nhưng đó sẽ chỉ là một trình bao bọc xung quanh một thư viện điều chỉnh hiệu suất xử lý tổng hợp thực tế, đúng không? Tôi đã đề cập đến một cách tiếp cận Ruby thuần túy. –

+0

Đây là một số mã Ruby để xuất ra .wav: https://github.com/cohena/RAFL/blob/master/RAFL_wav.rb – mgamba

Các vấn đề liên quan