2012-02-08 6 views
6

Tôi muốn đại diện cho tệp âm thanh trong hình ảnh có kích thước tối đa 180 × 180 pixel.Tạo hình thu nhỏ cho tệp âm thanh tùy ý

Tôi muốn tạo hình ảnh này sao cho nó bằng cách nào đó biểu thị tệp âm thanh, suy nghĩ về nó như dạng sóng của SoundCloud (biểu đồ biên độ)?.

Screenshot of Soundcloud's player

Tôi tự hỏi nếu có ai trong số các bạn có điều gì đó cho việc này. Tôi đã tìm kiếm xung quanh một chút, chủ yếu là "hiển thị âm thanh" và "thu nhỏ âm thanh", nhưng tôi không thấy bất kỳ điều gì hữu ích.

Tôi trước tiên posted this to ux.stackexchange.com, đây là nỗ lực của tôi để tiếp cận với bất kỳ lập trình viên nào làm việc về vấn đề này.

+0

Bạn có muốn tạo công cụ để thực hiện việc này hay bạn muốn có giải pháp đã tồn tại từ trước không? – Koof

+0

Đó không phải là một quang phổ, đó là biểu đồ biên độ. Phổ của âm thanh là ba d: thường là thời gian trên trục x, tần số trên y và biên độ được biểu thị bằng màu. –

+0

Cảm ơn bạn Josh Caswell, như bạn thấy, tôi đã không chắc chắn về tên của đại diện này của một dạng sóng. – joar

Trả lời

2

Hãy xem bài đăng trên blog này về wav2png.py.

3

Bạn cũng có thể chia âm thanh thành một phần và đo RMS (thước đo độ ồn). giả sử bạn muốn một hình ảnh rộng 180 pixel.

tôi sẽ sử dụng pydub, một wrapper nhẹ tôi đã viết xung quanh lib std wave modeule:

from pydub import AudioSegment 

# first I'll open the audio file 
sound = AudioSegment.from_mp3("some_song.mp3") 

# break the sound 180 even chunks (or however 
# many pixels wide the image should be) 
chunk_length = len(sound)/180 

loudness_of_chunks = [] 
for i in range(180): 
    start = i * chunk_length 
    end = chunk_start + chunk_length 

    chunk = sound[start:end] 
    loudness_of_chunks.append(chunk.rms) 

vòng lặp for có thể được biểu diễn dưới dạng danh sách hiểu biết sau đây, tôi chỉ muốn nó phải rõ ràng :

loudness_of_chunks = [ 
    sound[ i*chunk_length : (i+1)*chunk_length ].rms 
    for i in range(180)] 

Bây giờ suy nghĩ duy nhất còn lại để làm là mở rộng quy mô các RMS xuống một 0-180 quy mô (vì bạn muốn hình ảnh là 180px cao)

max_rms = max(loudness_of_chunks) 

scaled_loudness = [ (loudness/max_rms) * 180 for loudness in loudness_of_chunks] 

Tôi sẽ để lại các bản vẽ của các điểm ảnh thực tế để bạn, tôi không phải là rất có kinh nghiệm với PIL hoặc Imagemagick:/

+0

Chuyển đổi 'max_rms' thành phao trước. Nó giúp. – Remco

1

Dựa trên câu trả lời Jiaaro của (nhờ viết pydub!), Và xây dựng cho web2py đây hai xu của tôi:

def generate_waveform(): 
    img_width = 1170 
    img_height = 140 
    line_color = 180 
    filename = os.path.join(request.folder,'static','sounds','adg3.mp3') 


    # first I'll open the audio file 
    sound = pydub.AudioSegment.from_mp3(filename) 

    # break the sound 180 even chunks (or however 
    # many pixels wide the image should be) 
    chunk_length = len(sound)/img_width 

    loudness_of_chunks = [ 
     sound[ i*chunk_length : (i+1)*chunk_length ].rms 
     for i in range(img_width) 
    ] 
    max_rms = float(max(loudness_of_chunks)) 
    scaled_loudness = [ round(loudness * img_height/ max_rms) for loudness in loudness_of_chunks] 

    # now convert the scaled_loudness to an image 
    im = Image.new('L',(img_width, img_height),color=255) 
    draw = ImageDraw.Draw(im) 
    for x,rms in enumerate(scaled_loudness): 
     y0 = img_height - rms 
     y1 = img_height 
     draw.line((x,y0,x,y1), fill=line_color, width=1) 
    buffer = cStringIO.StringIO() 
    del draw 
    im = im.filter(ImageFilter.SMOOTH).filter(ImageFilter.DETAIL) 
    im.save(buffer,'PNG') 
    buffer.seek(0) 
    return response.stream(buffer, filename=filename+'.png')