Simultaneously read and write to buffer

Viewed 109

I am in the process of learning Julia and I'd like to do some buffer manipulation. What I want to achieve is the following:

I've got a buffer that I can write to and read from at the same time, meaning that the speed with which I add a value to the Fifo buffer approximately equals the speed with which I read from the buffer. Reading and writing will happen in separate threads so it can occur simultaneously. Additionally, I want to be able to control the values that I write into the buffer based on user input. For now, this is just a simple console prompt asking for a number, which I then want to write into the stream continously. The prompt refreshes and asks for a new number to write into the stream, but the prompt is non-blocking, meaning that in the background, the old number is written to the buffer until I enter a new number, which is then written to the buffer continuously.

This is my preliminary code for simulatenous reading and writing of the stream:

using Causal

CreateBuffer(size...) = Buffer{Fifo}(Float32, size...)

function writetobuffer(buf::Buffer, n::Float32)
    while !isfull(buf)
        write!(buf, fill(n, 2, 1))
    end
end

function readfrombuffer(buf::Buffer)
    while true
        while !isempty(buf)
            @show read(buf)
        end
    end
end

n_channels = 2
sampling_rate = 8192
duration = 2
n_frames = sampling_rate * duration
sbuffer = CreateBuffer(n_channels, n_frames)

print("Please enter a number: ")
n = parse(Float32, readline())

s1 = Threads.@spawn writetobuffer(sbuffer, n)
s2 = Threads.@spawn readfrombuffer(sbuffer)
s1 = fetch(s1)
s2 = fetch(s2)

I am not sure how to integrate the user input in a way that it keeps writing and reading the latest number the user put in. I looked at the documentation for channels, but didn't manage to get it working in a way that was non-blocking for the stream writing. I don't know that the correct approach is (channels, events, julia's multithreading) to enable this functionality. How would I go on about to include this?

1 Answers

I managed to get it working, but I think it could be improved:

using Causal

CreateBuffer(size...) = Buffer{Fifo}(Float32, size...)

function writeToBuffer(buf::Buffer, n::Float32)
    write!(buf, fill(n, 2, 1))
end

function readFromBuffer()
    global soundbuffer

    println("Starting")
    sleep(0.5)
    while true
        while !isempty(soundbuffer)
            read(soundbuffer)
        end
    end
    println("Exiting...")
end

function askForInput()::Float32
    print("Please enter a number: ")
    a = parse(Float32, readline())
    return(a)
end

function inputAndWrite()
    global soundbuffer

    old_num::Float32 = 440
    new_num::Float32 = 440
    while true
        @async new_num = askForInput()

        while (new_num == old_num)
            writeToBuffer(soundbuffer, new_num)
        end

        old_num = new_num
        println("Next iteration with number " * string(new_num))
    end
end

n_channels = 2
sampling_rate = 8192
duration = 2
n_frames = sampling_rate * duration
soundbuffer = CreateBuffer(n_channels, n_frames)

s1 = Threads.@spawn inputAndWrite()
s2 = Threads.@spawn readFromBuffer()
s1 = fetch(s1)
s2 = fetch(s2)
Related