Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

playing a chord in python

I want to do make a platform to play chords like guitar does. For example - to play the E chord it playes [0, 2, 2, 1, 0, 0] (from the Low-E string to the High-E string).

I'm trying to play chords on python by playing all the different strings simultaneously (by using threads).

The problem is that every time I start playing the next strings, it seems that the last string stops playing, and that the new one replaces it. So all I hear after playing a chord is the highest string (the last one).

Do I use the threads not correctly? Or is it a problem with the current functions? Or maybe it's the winsound.Beep() function that canwt handle these kind of things?

This is my code:

from winsound import Beep
import threading
import time


def play(freq, dur):
    Beep(round(freq), round(dur))


def get_freq(string, fret):
    a3_freq = 220
    half_tone = 2 ** (1 / 12)

    higher_from_a3_by = 5 * (string - 2) + fret
    if string > 4:
        higher_from_a3_by += 1
    return a3_freq * half_tone ** higher_from_a3_by


def strum(string, fret, time):
    freq = get_freq(string, fret)
    t = threading.Thread(target=play, args=(freq, time))
    t.start()
    return t


def chord(frets, dur):
    threads = []
    for i in range(6):
        if frets[i] != -1:
            threads.append(strum(i + 1, frets[i], dur))
    for t in threads:
        t.join()


chord((-1, 0, 2, 2, 2, 0), 1000) # plays the A chord for one second, for example.

From what I've cheacked, the play() and get_freq() functions donwt have any problem.

So what is the problem, and how can I fix it?

Edit:

I've tried it in C# but it didn't work either. Is this the right way of starting threads in C#?

foreach (Thread t in threads)
    t.Start();
foreach (Thread t in threads)
    t.Join();
like image 658
Tom Avatar asked Oct 29 '16 11:10

Tom


1 Answers

Gevent would make this much easier. Though still technically single threaded, context switching is so fast it would make it appear simultaneous. You can even use GIPC for multithreaded bi-directional multiprocess communication.

However I think your problem is much simpler. Your issue is the windsound module. Beep is not asynchoronous. So that is your limitation. You need to use

winsound.SND_ASYNC

This will allow you to send multiple events to play simultaneously.

like image 111
eatmeimadanish Avatar answered Oct 01 '22 10:10

eatmeimadanish