Hello! I’m having a hard time understanding why this code isn’t sleeping for the whole duration. What I am trying to do is iterate through these rows of arrays. I want each row to play for a certain duration, then pause before the next one. In each row, there are samples. These samples are split among each other. What is happening, however, is that samples from the next row are playing over before one row is finished. Does this make sense? Let me know if I need to explain it further and thanks for your help.
require 'csv'
path = '/Users/maxgraze/Desktop/Projects/German speaking'
processGap = 0.5
define :convertToMin do |string|
return (string[1..3].sub(':','.').to_f*100 + string[0].to_f*60)/100
end
processGap = 0.5
data = []
CSV.foreach(path + '/data.csv', headers: true) do |row|
types = row[3]
next if types.nil?
if types.include?(',')
# Split the row into an array
types = types.split(',').map(&:strip)
end
data << row.to_h
end
puts("Transformed", data[3]['type'])
def normalize(x, xmin, xmax, ymin, ymax)
xrange = xmax - xmin
yrange = ymax - ymin
ymin + (x - xmin) * (yrange.to_f / xrange)
end
def sample_duration(sample_path)
info = SonicPi::Core::SampleInfo.new(sample_path)
info.duration
end
live_loop :westbam do
sample path + '/westbam.wav', amp: 0.2, attack: 2
end
total_duration = 0
##| sleep 5
data.each do |row|
types = row['type'].look
puts("data types:", row['type'])
bucket = row["bucket"].look.strip.to_i
norm_bucket = normalize(bucket, 0, 8, 0, 1)
puts("norm_bucket:", norm_bucket)
length = row["type"].split(", ").length
puts("length:", length)
total_duration = norm_bucket/length
puts("total duration:", total_duration)
# Calculate the total duration of all the samples being played
row["type"].split(", ").each do |type|
puts("type:", type)
filename = "#{type}.wav"
full_path = "#{path}/#{filename}"
sample full_path, finish: total_duration
##| sample_duration = norm_bucket
##| total_duration += sample_duration
##| puts("sample duration:", sample_duration)
##| puts("total duration:", total_duration)
##| end
##| sleep norm_bucket + 2
sleep norm_bucket + 2
end
sleep 2
# Sleep for the total duration of the samples being played
end
unfortunately the code you have posted is rather complex so it’s hard to see where your issue is.
Please could you try to reduce the complexity (i.e. remove all csv processing etc.) and share the smallest code which produces the issues you’re obvserving. Then at that point it will be useful to share the code, share what you expect it to do and then what you’re observing so we can see what the issue. might be.
While I haven’t really parsed everything going on in your code, at first glance, I am curious why you have chosen to define your own function called sample_duration when there is already a built in function called sample_duration that can be used to play a sample for the exact duration of the sample length. It would seem like that would be your best bet if you are trying to make sure your samples don’t overlap. This would make more sense to use with each individual sample in the array as opposed to calculating the total duration of the samples in the array. Is there a specific reason you want to do that?
Here is a very simple example of how you could play through an array of samples, wait a bit and then play through a different array of samples:
samps = [:elec_bong, :ambi_drone, :loop_amen, :mehackit_robot1]
samps2 = [:misc_crow, :glitch_perc5, :guit_em9, :vinyl_backspin]
define :play_sample_array do |s|
s.length.times do |i|
sample s[i]
sleep sample_duration s[i]
end
end
play_sample_array samps
sleep 2
play_sample_array samps2
Apologies if this is missing the point of what you are trying to do.
Hi! Thanks so much for your help. I realize I didn’t explain well what I am trying to do. The point of it is to create a sonification. Each row has certain samples associated with it (conversation, service, etc) and a value (‘bucket’ 0 - 7). I want the entirety of the samples in a given row to respond to the bucket value. For example, if one row’s value is 2, all the samples in that row will only play for however long ‘2’ is normalized to. Does that make sense? But now when I play them, they are all overlapping, and samples in one row are not finished before the samples in the next row start.
all the samples in that row will only play for however long ‘2’ is normalized to.
I am not clear on what you mean by “normalized to”. What is happening when something is “normalized”? Can you give an example of what this would look like? What would ‘2’ be normalized to?
I see the “normalize” function you have defined in your code. it looks like you are “mapping” one range of values to another range of values. This post shows a formula that looks similar to the one you have. Is this what you are trying to do? If so, how would this connect to the duration for each row of samples?
require 'csv'
sp = '/home/raulmate/Audio/sample.csv'
data = CSV.read(sp)
s = data.length
s.times do |i|
d = data[i][1].to_i
ds = data[i][2].to_i
sample data[i][0]+'.flac',sustain: d
sleep ds
end
The normalization method is because ‘finish’ needs to be a value between 0 & 1. So I normalize the buckets (0-7) so that they have a value between 0 & 1.
The data looks like this. “bucket” just refers to the approximate total duration of the activities on a given day. I only want the entire row to play for as long as the bucket is. So if the bucket is shorter, the samples will place for less time.
I just realized the problem. It’s with the ‘finish.’ I didn’t realize that ‘finish’ calculated a point in the sample. I just want the sample to finish at a time I specify, like 2 seconds, for example. How can I do this?
I ended up figuring it out, but this version is MUCH nicer! Thanks so much. My next improvement will be to try to get the first item in the row to play for the entirety of the row’s duration if it belongs to a certain type…but I am doubting I will ever get there since this project dragged out for too long.