13 Commits

Author SHA1 Message Date
68f8cff151 padding 2025-07-09 11:21:02 +02:00
e85ed8371d timeline clickable 2025-07-09 11:18:15 +02:00
bf2266955b add remove point 2025-07-09 09:33:26 +02:00
4d31708481 change sounds 2025-07-09 01:35:16 +02:00
8f850e9323 fix all polyframe update now 2025-07-09 01:31:03 +02:00
51757c3922 Merge branch 'master' of gitlab.dukantic.fr:dukantic/polymusic 2025-07-09 00:56:55 +02:00
50251b3053 fix assets 2025-07-09 00:56:33 +02:00
00ea324d48 Delete .gitlab-ci.yml 2025-07-08 21:39:21 +00:00
1192c22691 Update .gitlab-ci.yml file 2025-07-08 21:38:08 +00:00
01ad529024 Update .gitlab-ci.yml file 2025-07-08 21:34:48 +00:00
44b96aef15 Edit README.md 2025-07-08 21:32:52 +00:00
27529e4fc5 Update .gitlab-ci.yml file 2025-07-08 21:29:21 +00:00
a56f5ddba4 Update .gitlab-ci.yml file 2025-07-08 21:15:57 +00:00
49 changed files with 112 additions and 32 deletions

View File

@@ -1,4 +1,9 @@
# Polymusic
Polymusic is an innovative music application inspired
by two academic research papers that explore sound
generation through balanced polygons. By leveraging
geometric principles, Polymusic produces harmonious
and rich audio textures, creating a unique auditory experience.
## Instalation

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/a-3.mp3 Normal file

Binary file not shown.

BIN
assets/a-4.mp3 Normal file

Binary file not shown.

BIN
assets/a-5.mp3 Normal file

Binary file not shown.

BIN
assets/a3.mp3 Normal file

Binary file not shown.

BIN
assets/a4.mp3 Normal file

Binary file not shown.

BIN
assets/a5.mp3 Normal file

Binary file not shown.

BIN
assets/b3.mp3 Normal file

Binary file not shown.

BIN
assets/b4.mp3 Normal file

Binary file not shown.

BIN
assets/b5.mp3 Normal file

Binary file not shown.

BIN
assets/c-3.mp3 Normal file

Binary file not shown.

BIN
assets/c-4.mp3 Normal file

Binary file not shown.

BIN
assets/c-5.mp3 Normal file

Binary file not shown.

BIN
assets/c3.mp3 Normal file

Binary file not shown.

BIN
assets/c4.mp3 Normal file

Binary file not shown.

BIN
assets/c5.mp3 Normal file

Binary file not shown.

BIN
assets/c6.mp3 Normal file

Binary file not shown.

BIN
assets/d-3.mp3 Normal file

Binary file not shown.

BIN
assets/d-4.mp3 Normal file

Binary file not shown.

BIN
assets/d-5.mp3 Normal file

Binary file not shown.

BIN
assets/d3.mp3 Normal file

Binary file not shown.

BIN
assets/d4.mp3 Normal file

Binary file not shown.

BIN
assets/d5.mp3 Normal file

Binary file not shown.

BIN
assets/e3.mp3 Normal file

Binary file not shown.

BIN
assets/e4.mp3 Normal file

Binary file not shown.

BIN
assets/e5.mp3 Normal file

Binary file not shown.

BIN
assets/f-3.mp3 Normal file

Binary file not shown.

BIN
assets/f-4.mp3 Normal file

Binary file not shown.

BIN
assets/f-5.mp3 Normal file

Binary file not shown.

BIN
assets/f3.mp3 Normal file

Binary file not shown.

BIN
assets/f4.mp3 Normal file

Binary file not shown.

BIN
assets/f5.mp3 Normal file

Binary file not shown.

BIN
assets/g-3.mp3 Normal file

Binary file not shown.

BIN
assets/g-4.mp3 Normal file

Binary file not shown.

BIN
assets/g-5.mp3 Normal file

Binary file not shown.

BIN
assets/g3.mp3 Normal file

Binary file not shown.

BIN
assets/g4.mp3 Normal file

Binary file not shown.

BIN
assets/g5.mp3 Normal file

Binary file not shown.

View File

@@ -1,9 +1,13 @@
mod polygon_draw;
use iced::widget::canvas::Program;
use polygon_draw::Polygon;
mod music;
use music::Music;
mod message;
use message::Message;
mod utils;
use utils::str_to_sec;
@@ -38,27 +42,6 @@ fn main() -> iced::Result {
.run_with(MyApp::new)
}
#[derive(Debug, Clone)]
enum Message {
ButtonPressedIncrement,
ButtonPressedDecrement,
Tick,
AddPolygon(String),
ChangeTeta(usize, f32),
Remove(usize),
ChangeColor(usize, String),
ChangeSound(usize, String),
ToggleSavePanel,
Save,
Load,
FileNameChanged(String),
TogglePaused,
SetMusicLength,
LengthChange(String),
ChangeDelta(f32),
AddPoint,
}
struct MyApp {
music: Music,
time_last_frame: Instant,
@@ -139,7 +122,7 @@ impl MyApp {
Ok(j) => {
let decoded: Music = serde_json::from_str(&j).unwrap();
self.music = decoded;
self.music.update_frame(self.current_delta);
self.music.update_frame();
}
Err(e) => {
eprintln!("Error, no saves with this name to load, {e} ");
@@ -173,6 +156,12 @@ impl MyApp {
Message::AddPoint => {
self.music.add_point(self.current_delta);
}
Message::RemovePoint => {
self.music.remove_point(self.current_delta);
}
Message::ClickedOnTimeLine(f) => {
self.update(Message::ChangeDelta(f));
}
}
}
@@ -315,20 +304,23 @@ impl MyApp {
delta_to_string(self.music.length)
))
.size(20.0),
button("Add Point").on_press(Message::AddPoint)
button("Add Point").on_press(Message::AddPoint),
button("Remove Point").on_press(Message::RemovePoint),
]
.spacing(20),
column![
/*
slider(0.0..=self.music.length, self.current_delta, move |f| {
Message::ChangeDelta(f)
})
.step(&self.music.length / 10_000.),
.step(&self.music.length / 10_000.),*/
canvas(&self.music)
.height(Length::FillPortion(1))
.width(Length::FillPortion(1))
]
.spacing(0),
]
.spacing(20)
.height(Length::FillPortion(1))
.width(Length::FillPortion(1)),
]

22
src/message.rs Normal file
View File

@@ -0,0 +1,22 @@
#[derive(Debug, Clone)]
pub enum Message {
ButtonPressedIncrement,
ButtonPressedDecrement,
Tick,
AddPolygon(String),
ChangeTeta(usize, f32),
Remove(usize),
ChangeColor(usize, String),
ChangeSound(usize, String),
ToggleSavePanel,
Save,
Load,
FileNameChanged(String),
TogglePaused,
SetMusicLength,
LengthChange(String),
ChangeDelta(f32),
AddPoint,
RemovePoint,
ClickedOnTimeLine(f32),
}

View File

@@ -1,10 +1,15 @@
use crate::message::Message;
use crate::utils::string_to_polygon;
use crate::{polygon_draw::*, utils::string_to_color};
use serde::{Deserialize, Serialize};
use kira::{AudioManager, sound::static_sound::StaticSoundData};
use iced::mouse;
use iced::event::Status;
use iced::mouse::Cursor;
use iced::widget::canvas::Event;
use iced::{mouse, padding};
use iced::widget::canvas;
use iced::widget::canvas::Stroke;
use iced::widget::canvas::Style;
@@ -35,6 +40,17 @@ impl Music {
&mut self.poly_frame.last_mut().unwrap().1
}
}
fn find_index_frame(&mut self, delta: f32) -> usize {
if let Some(i) = self
.poly_frame
.windows(2)
.position(|w| w[0].0 <= delta && delta < w[1].0)
{
i
} else {
self.poly_frame.len() - 1
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~PUBLIC~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pub fn current_frame(&self, delta: f32) -> &PolygonFrame {
if let Some(i) = self
@@ -59,8 +75,10 @@ impl Music {
}
}
pub fn update_frame(&mut self, delta: f32) {
self.find_poly_frame(delta).update();
pub fn update_frame(&mut self) {
for (_, p) in &mut self.poly_frame {
p.update();
}
}
pub fn fix_teta(&mut self, delta: f32) {
@@ -119,6 +137,12 @@ impl Music {
self.poly_frame
.insert(pos, (delta, self.current_frame(delta).clone()));
}
pub fn remove_point(&mut self, delta: f32) {
let i = self.find_index_frame(delta);
if i != 0 {
self.poly_frame.remove(i);
}
}
pub fn add_polygon(&mut self, delta: f32, polygon_name: String) {
let current_frame = self.find_poly_frame(delta);
@@ -130,13 +154,13 @@ impl Music {
self.find_poly_frame(delta).polygons.remove(i);
}
}
impl<Message> canvas::Program<Message> for Music {
impl canvas::Program<Message> for Music {
// No internal state
type State = ();
type State = bool;
fn draw(
&self,
_state: &(),
_state: &Self::State,
renderer: &Renderer,
_theme: &Theme,
bounds: Rectangle,
@@ -147,7 +171,7 @@ impl<Message> canvas::Program<Message> for Music {
let padding = 8.;
let w = bounds.width - (padding * 2.);
for (delta, _) in &self.poly_frame {
let x = delta / self.length * w + padding;
let x = delta / self.length * w + 8.;
frame.fill_rectangle(
iced::Point { x: x, y: 0.0 },
frame.size(),
@@ -168,7 +192,7 @@ impl<Message> canvas::Program<Message> for Music {
},
);
let x = self.current_delta / self.length * w + padding;
let x = self.current_delta / self.length * w + 8.;
frame.stroke_rectangle(
iced::Point::new(x, 0.),
iced::Size {
@@ -185,4 +209,41 @@ impl<Message> canvas::Program<Message> for Music {
// Then, we produce the geometry
vec![frame.into_geometry()]
}
fn update(
&self,
state: &mut Self::State,
event: Event,
bounds: Rectangle,
cursor: Cursor,
) -> (Status, Option<Message>) {
//eprintln!("event = {:?}", event);
if let Event::Mouse(mouse_event) = event {
match mouse_event {
mouse::Event::ButtonPressed(mouse::Button::Left) => {
*state = true;
if let Some(position) = cursor.position_in(bounds) {
let pos_x = (position.x - 8.0) / (bounds.width - 16.);
let delta = (pos_x * self.length).clamp(0., self.length);
return (
Status::Captured,
Some(crate::message::Message::ClickedOnTimeLine(delta)),
);
}
}
mouse::Event::ButtonReleased(mouse::Button::Left) => *state = false,
mouse::Event::CursorMoved { position: _ } => {
if let Some(position) = cursor.position_in(bounds)
&& *state
{
let pos_x = (position.x - 8.0) / (bounds.width - 16.);
let delta = (pos_x * self.length).clamp(0., self.length);
return (Status::Captured, Some(Message::ClickedOnTimeLine(delta)));
}
}
_ => {}
}
}
(Status::Ignored, None)
}
}