How can you make one file, for example: "out.wav", and in it add "1.wav" 10 times, but without delays. That is, to superimpose the sound on another sound even if the previous one has not finished playing. As I've been trying to do for about an hour and a half now, and all I get is playback one by one (i.e.: first the sound plays completely)
Simplest code:
use hound::{WavReader, WavWriter};
fn main() {
let mut reader = WavReader::open("1.wav").unwrap();
let spec = reader.spec();
let mut writer = WavWriter::create("output.wav", spec).unwrap();
for _ in 0..10 {
for sample in reader.samples::<i16>() {
writer.write_sample(sample.unwrap()).unwrap();
}
reader.seek(0).unwrap();
}
}
You have to somehow read & mix the multiple sounds you want to play at the same time.
Here is an example that plays 10 times the same sound each delayed by half that sounds length,
mixed by simply averaging both clips playing at the same time.
use hound::{WavReader, WavWriter};
fn main() {
let mut reader = WavReader::open("1.wav").unwrap();
let mut reader2 = WavReader::open("1.wav").unwrap();
let mut writer = WavWriter::create("output.wav", spec).unwrap();
let l = reader.len();
reader.seek(l/2).unwrap();
for i in 0..l*10 {
if i % (l/2) == 0 {
reader.seek(0).unwrap();
let tmp = reader;
reader = reader2;
reader2 = tmp;
}
let s1 = reader.samples::<i16>().next().unwrap().unwrap();
let s2 = reader2.samples::<i16>().next().unwrap().unwrap();
let sample = s1/2 + s2/2;
writer.write_sample(sample).unwrap();
}
}
Which can definitely be cleaned up a lot (ie store the samples in a Vec once and just read from there)
Related
So I want to get the distance in cm from my sensor, I already did it with Arduino C and an Arduino compatible board. Now I want to do this with stm32, below is my code (leaving out the conversion of pulse length to sound, as the delta time is constant already at this point.
#![deny(unsafe_code)]
#![allow(clippy::empty_loop)]
#![no_main]
#![no_std]
use panic_halt as _; // panic handler
use cortex_m_rt::{entry, interrupt};
use stm32f4xx_hal as hal;
use crate::hal::{pac, prelude::*};
use stm32f4xx_hal::delay::Delay;
use rtt_target::{rtt_init_print, rprintln};
use stm32f4xx_hal::timer::{Counter, Timer, SysCounter, CounterUs};
use cortex_m::peripheral::SYST;
use stm32f4xx_hal::time::Hertz;
use core::fmt::Debug;
use stm32f4xx_hal::pac::TIM2;
use core::pin::Pin;
fn dbg<T: Debug>(d: T, tag: &str) -> T {
rprintln!("{} {:?}", tag, d);
d
}
fn waste(c_us: &CounterUs<TIM2>, us: u32) {
let ts1 = c_us.now().ticks();
while (c_us.now().ticks() - ts1) < us {}
}
fn waste_until<T>(c_us: &CounterUs<TIM2>,
predicate: fn(_: &T) -> bool,
dt: &T,
us: u32) -> u32 {
let ts1 = c_us.now().ticks();
while (c_us.now().ticks() - ts1) < us && !predicate(dt) {}
return c_us.now().ticks() - ts1;
}
#[entry]
fn main() -> ! {
if let (Some(dp), Some(cp)) = (
pac::Peripherals::take(),
cortex_m::peripheral::Peripherals::take(),
) {
rtt_init_print!();
let gpioa = dp.GPIOA.split();
let mut trig = gpioa.pa3.into_push_pull_output();
let mut echo = gpioa.pa4.into_pull_up_input();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.freeze();
let mut counter = Timer::new(dp.TIM2, &clocks).counter_us();
counter.start(1_000_000_u32.micros()).unwrap();
loop {
trig.set_low();
waste(&counter, 2);
trig.set_high();
waste(&counter, 10);
trig.set_low();
let _ = waste_until(&counter, |c|c.is_high(),&echo, 1000);
let pulse_duration = waste_until(&counter, |c| c.is_low(),&echo, 1000);
rprintln!("{}", pulse_duration);
}
}
loop {}
}
I know that the code at this point does not stop the evaluation of the data in the case of timeout in the waste_until function, but given that there is an object less then 10 cm from sensor (which has a range of up to 2 meters) it shouldn't be causing issues.
I have few things I don't understand completely, which I assume might be the cause of this behavior.
First of all, I'm not sure if hardware timers loop, or have to be reset manually. (I used my waste function with half a second delay and managed to make seemingly ok blinky program, so i hope i got it correct).
I'm not sure if i have to configure my TIM2 maximum sampling frequency as in theory I could do it with sysclock, but i didn't find a way to do it with TIM2. Also I assumed that it wouldn't let me create CounterUs without minimum valid sample rate.
I'm not sure if ticks() are in one to one relation with microseconds (only assumed so, because it seemed logical that CounterUs would do that).
I'm not sure about the problems which might occur if timer loops mid wait and delta time becomes negative (in case of u32 just overflows).
When it comes to pull_up_input and pull_down_input does pull_up refer to the fact that pin is usually pulled high, and to trigger logical one it has to go low or that it has to be pulled high to get logical one? (Also it is not very clear if the is_low() and is_high() methods refer to the state of the pin, or logical value of the pin?)
I spent quite some time on this thing, but sadly to no avail so far. Hopefully someone can tell me if one of the things above is wrong and indeed causes the issue, or if its not something I considered helped me to see it.
(Value I'm getting is 1000 - 1001)
So from one of the comments I found out about the pull down and pull up resistors and watched couple YouTube videos on the matter. Not sure if this is correct, but from what I've found it seems that in fact i need a pull_down_input for echo pin. So I replaced it and the value
I'm getting is still constant but it's 1 now.
Now that makes some sense, since I assume that 1000 was originating from the timeout value in my waste. But getting 1 is a bit more confusing, I mean it cannot be faster then 1 us, right?
So after experimenting some more, I've ended up with this version of the code:
#![deny(unsafe_code)]
#![allow(clippy::empty_loop)]
#![no_main]
#![no_std]
use panic_halt as _; // panic handler
use cortex_m_rt::{entry, interrupt};
use stm32f4xx_hal as hal;
use crate::hal::{pac, prelude::*};
use stm32f4xx_hal::delay::Delay;
use rtt_target::{rtt_init_print, rprintln};
use stm32f4xx_hal::timer::{Counter, Timer, SysCounter, CounterUs};
use cortex_m::peripheral::SYST;
use stm32f4xx_hal::time::Hertz;
use core::fmt::Debug;
use stm32f4xx_hal::pac::TIM2;
use core::pin::Pin;
use cortex_m::asm::nop;
fn dbg<T: Debug>(d: T, tag: &str) -> T {
rprintln!("{} {:?}", tag, d);
d
}
fn waste(c_us: &CounterUs<TIM2>, us: u32) {
let ts1 = c_us.now().ticks();
while (c_us.now().ticks() - ts1) < us {}
}
fn waste_until<T>(c_us: &CounterUs<TIM2>,
predicate: fn(_: &T) -> bool,
dt: &T,
us: u32) -> Option<u32> {
let ts1 = c_us.now().ticks();
while (c_us.now().ticks() - ts1) < us && !predicate(dt) {
}
if predicate(dt) {Some(c_us.now().ticks() - ts1)} else {None}
}
#[entry]
fn main() -> ! {
if let (Some(dp), Some(cp)) = (
pac::Peripherals::take(),
cortex_m::peripheral::Peripherals::take(),
) {
rtt_init_print!();
let gpioa = dp.GPIOA.split();
let mut trig = gpioa.pa4.into_push_pull_output();
let mut echo = gpioa.pa5.into_pull_down_input();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.freeze();
let mut counter = Timer::new(dp.TIM2, &clocks).counter_us();
counter.start(1_000_000_u32.micros()).unwrap();
loop {
// starting pulse
trig.set_low();
waste(&counter, 2);
trig.set_high();
waste(&counter, 10);
trig.set_low();
// ending pulse
// starting echo read
if let Some(_) = waste_until(&counter, |c|c.is_high(),&echo, 1_000_000) { // if didn't timeout
if let Some(pulse_duration) = waste_until(&counter, |c| c.is_low(),&echo, 1_000_000) { // if didn't timeout
rprintln!("{}", pulse_duration);
} else {
rprintln!("no falling edge");
}
} else {
rprintln!("no rising edge");
}
// end echo read
}
}
loop {}
}
And here it became clear that the pattern in fact was that first 1-3 readings output same value (so far I've seen 1, 21 and 41) and then it keeps timing out in the outer if.
I tried changing io pins because I considered that my poor solder job was to blame, and also inspected the pins with multimeter, they seem to be fine.
I'm not entirely sure but I think that given that sensor has a recommended VCC of 5 volts, and stlink-2 provides 3.3 volts to the board the sensor can preform worse (but once again the target object is at most 5 cm away).
Here are the images of my breadboard just in case i missed something.
I am trying to process vector with while loop. currently it is sequential taking each element at a time. Is there a way to process vector elements in parallel with rayon and get the same result. Will it increase the performance of the code given below? Basically I am getting continuous messages from tcp client and converting them in to vector and then process them. I want to make processing part faster. sample code is given below.
fn main() {
let r = process(false);
}
fn process (choice: bool) -> i32 {
let mut i = 0;
let my_string = "s1/s2/s3/s4/s5/s6/s7".to_string();
let my_vector: Vec<&str> = my_string.as_str().split("/").collect();
let mut tag_path = "MyString".to_string();
let mut message = "Variable = ".to_string();
let mut root_path = "".to_string();
return if !choice {
while i < my_vector.len() {
tag_path += "/";
tag_path += my_vector[i];
if i != my_vector.len() - 1 {
message = tag_path.clone();
let my_target_1 = tag_path.clone() + ":";
println!("{}", my_target_1)
} else {
let my_target_2 = tag_path.clone() + ",";
println!("{}", my_target_2);
}
root_path = message.clone();
i += 1;
}
1
} else {
0
}
}
Your code is not slow because you are missing parallelism opportunities, but rather because you are copying ever longer strings in a way that is reminiscent of Shlemiel the Painter's algorithm. Remember that copying strings runs in linear time in the length of the string.
(Kids, this is why basic computer science is so important!)
Since some parts of your snippet are irrelevant to your actual problem (e.g., the choice argument), I have taken the liberty of removing them from my answer. After simplifying your code, what I obtained is this:
fn main() {
let domain = "example.com";
let path = "s1/s2/s3/s4/s5/s6/s7";
let matches = path.match_indices('/');
for (pos, _) in matches {
println!("{}/{}:", domain, &path[0..pos]);
}
println!("{}/{},", domain, path)
}
To print a prefix of the full path, you just need to take a slice starting at the beginning of the path (i.e., the 0-th character) and ending just before the corresponding '/' (i.e., the pos-th character). This explains the line in the for loop.
I'm trying to solve my first ever project Euler problem just to have fun with Rust, and got stuck on what seems to be an extremely long compute time to solve
Problem:
https://projecteuler.net/problem=757
I came up with this code to try to solve it, which I'm able to solve the base problem (up to 10^6) in ~245 ms and get the expected result of 2,851.
use std::time::Instant;
fn factor(num: u64) -> Vec<u64> {
let mut counter = 1;
let mut factors = Vec::with_capacity(((num as f64).log(10.0)*100.0) as _);
while counter <= (num as f64).sqrt() as _ {
let div = num / counter;
let rem = num % counter;
if rem == 0 {
factors.push(counter);
factors.push(div);
}
counter += 1
}
factors.shrink_to_fit();
factors
}
fn main() {
let now = Instant::now();
let max = 10u64.pow(6);
let mut counter = 0;
'a: for i in 1..max {
// Optimization: All numbers in the pattern appear to be evenly divisible by 4
let div4 = i / 4;
let mod4 = i % 4;
if mod4 != 0 {continue}
// Optimization: And the remainder of that divided by 3 is always 0 or 1
if div4 % 3 > 1 {continue}
let mut factors = factor(i);
if factors.len() >= 4 {
// Optimization: The later found factors seem to be the most likely to fit the pattern, so try them first
factors.reverse();
let pairs: Vec<_> = factors.chunks(2).collect();
for paira in pairs.iter() {
for pairb in pairs.iter() {
if pairb[0] + pairb[1] == paira[0] + paira[1] + 1 {
counter += 1;
continue 'a;
}
}
}
}
}
println!("{}, {} ms", counter, now.elapsed().as_millis());
}
It looks like my code is spending the most amount of time on factoring, and in my search for a more efficient factoring algorithm than what I was able to come up with on my own, I couldn't find any rust code already made (the code I did find was actually slower.) But I did a simulation to estimate how long it would take even if I had a perfect factoring algorithm, and it would take 13 days to find all numbers up to 10^14 with the non-factoring portions of this code. Probably not what the creator of this problem intends.
Given I'm relatively new to programming, is there some concept or programming method that I'm not aware of (like say using a hashmap to do fast lookups) that can be used in this situation? Or is the solution going to involve spotting patterns in the numbers and making optimizations like the ones I have found so far?
If Vec::push is called when the vector is at its capacity, it will re-allocate its internal buffer to double the size and copy all its elements to this new allocation.
Vec::new() creates a vector with no space allocated so it will be doing this re-allocation.
You can use Vec::with_capacity((num/2) as usize) to avoid this and just allocate the max you might need.
Is there any mistake I am making in applying delay the delay?
This is the code I am working with to blink led 3 and 4 after with a delay.
use cortex_m_rt::entry;
use stm32f30x_hal as hal;
use hal::delay::Delay;
use hal::prelude::*;
use hal::stm32f30x;
use panic_halt;
#[entry]
fn main() -> ! {
let device_p = stm32f30x::Peripherals::take().unwrap();
let core_periphs=cortex_m::Peripherals::take().unwrap();
let mut reset_clock_control = device_p.RCC.constrain();
let mut gpioe = device_p.GPIOE.split(&mut reset_clock_control.ahb);
**let mut flash = device_p.FLASH.constrain();
let clocks = reset_clock_control.cfgr.freeze(&mut flash.acr);
let mut delay = Delay::new(core_periphs.SYST,clocks);**
let mut led_3 = gpioe
.pe9
.into_push_pull_output(&mut (gpioe.moder), &mut (gpioe.otyper));
let mut led_4=gpioe.pe8.into_push_pull_output(&mut gpioe.moder,&mut gpioe.otyper);
loop {
led_3.set_high();
**delay.delay_ms(2_000_u16);**
led_4.set_high();
}
}
If I am not using delay part it is working fine
I think you set up your clocks wrong. For the delay to work correctly you should use the system clock.
This is how to create the Delay for STM32 based on this sample (stm32f4xx, but should work for you, too):
// Set up the system clock. We want to run at 48MHz for this one.
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.sysclk(48.mhz()).freeze();
// Create a delay abstraction based on SysTick
let mut delay = hal::delay::Delay::new(cp.SYST, clocks);
where dp are my device peripherals (e.g. let dp = stm32::Peripherals::take().unwrap()) and cp are the core peripherals.
So this uses the sysclk.
Alternatively you could also try to replace your delay with cortex_m::delay(8_000_000);, where the delay is given using the number of clock cycles.
In the loop you set the LED high led_3.set_high();. However never set led_3 low again so it would never blink. So change your loop to:
led_3.set_high();
led_4.set_low();
delay.delay_ms(2_000_u16);
led_4.set_high();
led_3.set_low();
My plan is to write a simple method which does exactly what std::cin >> from the C++ standard library does:
use std::io::BufRead;
pub fn input<T: std::str::FromStr>(handle: &std::io::Stdin) -> Result<T, T::Err> {
let mut x = String::new();
let mut guard = handle.lock();
loop {
let mut trimmed = false;
let available = guard.fill_buf().unwrap();
let l = match available.iter().position(|&b| !(b as char).is_whitespace()) {
Some(i) => {
trimmed = true;
i
}
None => available.len(),
};
guard.consume(l);
if trimmed {
break;
}
}
let available = guard.fill_buf().unwrap();
let l = match available.iter().position(|&b| (b as char).is_whitespace()) {
Some(i) => i,
None => available.len(),
};
x.push_str(std::str::from_utf8(&available[..l]).unwrap());
guard.consume(l);
T::from_str(&x)
}
The loop is meant to trim away all the whitespace before valid input begins. The match block outside the loop is where the length of the valid input (that is, before trailing whitespaces begin or EOF is reached) is calculated.
Here is an example using the above method.
let handle = std::io::stdin();
let x: i32 = input(&handle).unwrap();
println!("x: {}", x);
let y: String = input(&handle).unwrap();
println!("y: {}", y);
When I tried a few simple tests, the method works as intended. However, when I use this in online programming judges like the one in codeforces, I get a complaint telling that the program sometimes stays idle or that the wrong input has been taken, among other issues, which leads to suspecting that I missed a corner case or something like that. This usually happens when the input is a few hundreds of lines long.
What input is going to break the method? What is the correction?
After a lot of experimentation, I noticed a lag when reading each input, which added up as the number of inputs were increased. The function doesn't make use of a buffer. It tries to access the stream every time it needs to fill a variable, which is slow and hence the lag.
Lesson learnt: Always use a buffer with a good capacity.
However, the idleness issue still persisted, until I replaced the fill_buf, consume pairs with something like read_line or read_string.