Compare commits

..

10 Commits

Author SHA1 Message Date
rltbg
07340588f4 Merge branch 'master' of https://moule.informatique.univ-paris-diderot.fr/guatto/progsync-m2-eidd-2025 2025-12-01 16:36:08 +01:00
Adrien Guatto
e8e6d683d4 journal cours 9 2025-12-01 16:07:58 +01:00
Adrien Guatto
6c8abfbade Corrections projet 2025-12-01 16:07:50 +01:00
LOTENBERG rayane
c1b9da418e Merge branch 'lotenber-master-patch-11857' into 'master'
Edit AUTEURS

See merge request batistac/progsync-m-2-projet!1
2025-11-19 17:30:36 +01:00
Adrien Guatto
70fc7019dc Cours 7 2025-11-10 18:12:19 +01:00
Adrien Guatto
88595d288f Fichiers audio, journal, annales 2025-11-04 18:33:00 +01:00
LOTENBERG rayane
b6d78aaa8c Edit AUTEURS 2025-11-04 15:12:30 +01:00
Adrien Guatto
abf505668e Typos sujet 2025-11-03 15:15:54 +01:00
Tiago Batista Cardoso
ccbc76c2fa [chore] projet structure 2025-11-03 11:36:34 +01:00
Adrien Guatto
7298fa66e1 Projet 2025-11-03 10:30:00 +01:00
157 changed files with 7308 additions and 286 deletions

2
AUTEURS Normal file
View File

@@ -0,0 +1,2 @@
BATISTA CARDOSO,TIAGO,tiago.batista-cardoso@etu.u-paris.fr
LOTENBERG, Rayane, rayane.lotenberg@etu.u-paris.fr

73
Makefile Normal file
View File

@@ -0,0 +1,73 @@
include Makefile.version
ASSET_DIR_PATH="\"$(shell pwd)/assets\""
CC?=gcc
CFLAGS=-Wall `pkg-config --cflags sdl2` -I `heptc -where`/c \
-D ASSET_DIR_PATH=$(ASSET_DIR_PATH) -D YEAR=$(ANNEE) \
-D VERSION=$(VERSION) -g -fsanitize=undefined
LDFLAGS=`pkg-config --libs sdl2` -lm -fsanitize=undefined
HEPTC?=heptc
HEPT_OBJ=\
src/challenge.o \
src/city.o \
src/globals.o \
src/vehicle.o \
src/control.o \
src/utilities.o \
src/challenge_types.o \
src/city_types.o \
src/globals_types.o \
src/vehicle_types.o \
src/control_types.o \
src/utilities_types.o
OBJ=$(HEPT_OBJ) \
src/buffer.o \
src/trace_lib.o \
src/trace.o \
src/debug.o \
src/mathext.o \
src/map.o \
src/cutils.o \
src/simulation_loop.o \
src/challenge.o \
src/main.o
TARGET=scontest
.SUFFIXES:
.PHONY: all clean test
.PRECIOUS: %.epci %.c %.h
.SUFFIXES:
all: $(TARGET)
clean:
rm -f $(OBJ) $(TARGET)
rm -f $(foreach ext, mls obc epci epo log, $(wildcard src/*.$(ext)))
rm -rf src/*_c
rm -f $(subst .o,.c,$(HEPT_OBJ))
rm -f $(subst .o,.h,$(HEPT_OBJ))
test: $(TARGET)
./$< -o logs.txt assets/00.map
$(TARGET): $(OBJ)
$(CC) $^ $(LDFLAGS) -o $@
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
%_types.c %.c %.h %.epci : %.ept src/mathext.epci src/debug.epci src/trace.epci
cd `dirname $<` && $(HEPTC) -c -target c `basename $<`
cp $(foreach ext,c h,$(basename $<)_c/*.$(ext)) src
%.epci: %.epi
cd `dirname $<` && $(HEPTC) `basename $<`
src/vehicle.epci: src/globals.epci src/utilities.epci src/control.epci
src/utilities.epci: src/globals.epci
src/control.epci: src/globals.epci src/utilities.epci
src/city.epci: src/globals.epci src/utilities.epci src/vehicle.epci src/map.epci
src/map.epci: src/map.epi src/globals.epci
src/challenge.epci: src/globals.epci src/vehicle.epci src/city.epci src/map.epci
src/main.o src/map.o: src/globals.h src/globals_types.h
src/simulation_loop.o: src/globals.h src/globals_types.h src/challenge.h

2
Makefile.version Normal file
View File

@@ -0,0 +1,2 @@
VERSION="\"1.1.0\""
ANNEE="\"2025-2026\""

View File

@@ -1,67 +1,6 @@
# Programmation Synchrone 2025-2026 (M2 Info & EIDD)
# Projet de Programmation synchrone
## Présentation
Ce répertoire contient le projet du cours de Programmation synchrone du M2
Informatique de l'Université de Paris et de l'École d'Ingénieur Denis Diderot.
Le [syllabus](cours/syllabus-progsync.pdf) (résumé) du module est disponible.
### Contenu et objectifs
Le module de *Programmation synchrone* propose une introduction à la
programmation des **systèmes réactifs** par le biais de langages spécialisés,
les **langages synchrones**.
- Les **systèmes réactifs** sont des systèmes informatiques en interaction
continue avec un environnement extérieur. Le pilote automatique d'un avion
moderne (_fly-by-wire_), le contrôleur d'une machine à laver, ou le logiciel
de commande d'un ascenseur constituent des exemples de systèmes réactifs.
- Les **langages synchrones** sont des langages spécialement conçus pour la
programmation des systèmes réactifs. Ils offrent une expressivité élevée tout
en garantissant statiquement certaines propriétés de sûreté. Leur usage est
désormais routinier dans les tâches conception et de développement dans
certains secteurs industriels, comme l'avionique ou le ferroviaire.
L'enseignement des langages synchrones vise deux objectifs. D'abord, **renforcer
vos compétences de programmation**, en vous faisant découvrir une famille de
langages à la fois originaux et utilisés dans l'industrie. Ensuite, **enrichir
votre culture scientifique**, en illustrant comment les systèmes réactifs
fournissent un exemple de point de jonction entre l'informatique et d'autres
disciplines comme l'automatique ou le traitement du signal.
Pour atteindre ces objectifs, on utilisera le langage universitaire
[*Heptagon*](https://gitlab.inria.fr/synchrone/heptagon), aussi bien durant le
cours magistral, pour illustrer les principes généraux des langages synchrones,
que durant les séances de travaux pratiques. Les autres langages synchrones
(notamment d'origines industrielles) seront aussi régulièrement évoqués durant
le cours.
## Organisation du cours
Le cours magistral a lieu le *lundi de 10h45 à 12h45*, dans la salle 1009 du
bâtiment Sophie Germain.
Les séances de travaux pratiques ont lieu en salle 2003 du bâtiment Sophie
Germain, avec deux groupes disponibles :
- le *mardi de 10h45 à 12h45*,
- le *jeudi de 08h30 à 10h30*.
Nous vous demandons **d'apporter votre ordinateur portable**.
## Modalités de contrôle des connaissances
La note du cours sera composée pour 50% de celle du projet et pour 50% de celle
de l'examen final. Les cours de master 2 n'offrent pas de deuxième session.
## Organisation de ce dépôt
Ce dépôt contiendra tout le matériel pédagogique du cours :
- le **support du cours**, dans les sous-répertoire [cours](cours/) et surtout
[notes](notes/),
- les **énoncés de TP**, dans le sous-répertoire [TP](tp/),
- l'**énoncé du projet, ainsi que son squelette**, seront ultérieurement
disponibles dans le sous-répertoire [projet](projet/).
Le [sujet](sujet/sujet-projet.pdf) contient tous les détails.

2
assets/00.iti Normal file
View File

@@ -0,0 +1,2 @@
go 20
stop 0.

17
assets/00.map Normal file
View File

@@ -0,0 +1,17 @@
map "oneway_line"
graphics "map_00_oneway_line.bmp"
guide "b-00.bmp"
init 50. 50. 23.703
rd 1
line 1 30 50. 50. 550. 250.
wp 1
0 550. 250.
tl 0
st 0
obst 2
30. 30. 1. 10.
200. 200. 8. 30.
iti 2
go 20.
stop
end

8
assets/01.iti Normal file
View File

@@ -0,0 +1,8 @@
go 20
turn 90.
go 20.
turn 90.
go 20.
turn 90.
go 20.
stop 0.

30
assets/01.map Normal file
View File

@@ -0,0 +1,30 @@
map "oneway_square"
graphics "map_01_oneway_square.bmp"
guide "b-01.bmp"
init 550. 200. 90.
rd 4
line 1 30 50. 50. 550. 50.
line 1 20 550. 50. 550. 250.
line 1 30 550. 250. 50. 250.
line 1 20 50. 250. 50. 50.
wp 5
0 548. 50.
1 550. 148.
1 550. 248.
2 52. 250.
3 50. 52.
tl 0
st 0
obst 2
30. 30. 1. 10.
200. 200. 8. 30.
iti 8
go 20
turn 90.
go 20.
turn 90.
go 20.
turn 90.
go 20.
stop 0.
end

2
assets/02.iti Normal file
View File

@@ -0,0 +1,2 @@
go 20
stop 0.

20
assets/02.map Normal file
View File

@@ -0,0 +1,20 @@
map "oneway_olympic"
graphics "map_02_oneway_olympic.bmp"
guide "b-02.bmp"
init 480. 100. 0.
rd 4
line 1 30 100. 100. 500. 100.
arc 1 20 500. 150. 50. -90. 90.
line 1 30 500. 200. 100. 200.
arc 1 20 100. 150. 50. 90. 270.
wp 1
0 449. 100.
tl 0
st 0
obst 2
30. 30. 1. 10.
200. 200. 8. 30.
iti 2
go 20
stop 0.
end

5
assets/03.iti Normal file
View File

@@ -0,0 +1,5 @@
go 20
go 15.
turn -44.
go 25.
stop 0.

29
assets/03.map Normal file
View File

@@ -0,0 +1,29 @@
map "oneway_ea"
graphics "map_03_oneway_ea.bmp"
guide "b-03.bmp"
init 20. 20. 35.
rd 5
line 1 20 5. 5. 100. 100.
line 1 20 100. 100. 160. 130.
line 1 20 160. 130. 230. 130.
arc 1 20 230. 230. 100. -90. 0.
line 1 20 230. 130. 330. 30.
wp 4
0 100. 100.
2 229. 130.
3 330. 230.
4 329. 31.
tl 2
0 60. 50. 5 3 5 7
2 220. 120. 5 3 5 10
st 2
0 0 50. 50.
2 1 220. 130.
obst 0
iti 5
go 20
go 15.
turn -44.
go 25.
stop 0.
end

6
assets/04.iti Normal file
View File

@@ -0,0 +1,6 @@
go 10
turn 90.
go 20.
turn 90.
go 10.
stop 0.

27
assets/04.map Normal file
View File

@@ -0,0 +1,27 @@
map "olympic_cut"
graphics "map_04_olympic_cut.bmp"
guide "b-04.bmp"
init 10. 150. 0.
rd 5
line 1 10 5. 150. 500. 150.
arc 1 20 100. 150. 50. 270. 90.
line 1 30 100. 200. 400. 200.
arc 1 20 400. 150. 50. 90. -90.
line 1 30 400. 100. 100. 100.
wp 4
0 48. 150.
0 448. 150.
0 498. 150.
3 449. 152.
tl 0
st 0
obst 0
iti 6
go 10
turn 90.
go 20.
turn 90.
go 10.
stop 0.
end

13
assets/05.iti Normal file
View File

@@ -0,0 +1,13 @@
go 10
turn 90.
go 20.
turn -90.
go 20.
go 30.
turn -90.
go 20
turn -90.
go 10
go 10
go 10
stop 0.

42
assets/05.map Normal file
View File

@@ -0,0 +1,42 @@
map "olympic_cut_tl"
graphics "map_05_olympic_cut_tl.bmp"
guide "b-05.bmp"
init 10. 150. 0.
rd 6
line 1 10 5. 150. 500. 150.
arc 1 20 100. 150. 50. 270. 90.
line 1 30 100. 200. 400. 200.
arc 1 20 400. 150. 50. 90. -90.
line 1 30 400. 100. 100. 100.
line 1 20 250. 200. 250. 100.
wp 8
0 48. 150.
0 448. 150.
0 498. 150.
3 450. 152.
2 248. 200.
5 250. 102.
5 250. 152.
0 248. 150.
tl 2
5 245. 160. 5 3 5 3
0 240. 145. 5 3 5 8
st 2
5 0 250. 160.
0 1 240. 150.
obst 0
iti 12
go 10
turn 90.
go 20.
turn -90.
go 20.
go 25.
turn -90.
go 20
turn -90.
go 10
go 10
go 10
stop 0.
end

13
assets/06.iti Normal file
View File

@@ -0,0 +1,13 @@
go 20.
turn -90.
go 10.
go 10.
go 10.
turn -90.
go 30.
turn -90.
go 10.
turn 90.
go 25.
stop 0.

44
assets/06.map Normal file
View File

@@ -0,0 +1,44 @@
map "roundabout"
graphics "map_06_roundabout.bmp"
guide "b-06.bmp"
init 60. 150. 0.
rd 10
line 1 20 50. 150. 100. 150.
arc 1 10 150. 150. 50. 180. 270.
line 1 30 150. 100. 150. 50.
arc 1 10 150. 150. 50. -90. 0.
line 1 30 200. 150. 250. 150.
arc 1 10 150. 150. 50. 0. 90.
line 1 30 150. 200. 150. 250.
arc 1 20 150. 150. 75. 0. -90.
arc 1 20 150. 150. 75. 90. 0.
arc 1 10 150. 150. 50. 90. 180.
wp 11
0 98. 150.
1 148. 100.4
2 150. 77.
2 150. 52.
3 199.9 148.
4 248. 150.
5 152. 199.9
6 150. 223.
6 150. 248.
8 224.8 153.
7 153. 75.2
tl 0
st 0
obst 0
iti 12
go 20.
turn -90.
go 10.
go 10.
go 10.
turn -90.
go 25.
turn -90.
go 10.
turn 90.
go 25.
stop 0.
end

13
assets/07.iti Normal file
View File

@@ -0,0 +1,13 @@
go 20.
turn -90.
go 10.
go 10.
go 10.
turn -90.
go 30.
turn -90.
go 10.
turn 90.
go 20.
stop 0.

53
assets/07.map Normal file
View File

@@ -0,0 +1,53 @@
map "roundabout_tl"
graphics "map_07_roundabout_tl.bmp"
guide "b-07.bmp"
init 60. 150. 0.
rd 10
line 1 20 50. 150. 100. 150.
arc 1 10 150. 150. 50. 180. 270.
line 1 30 150. 100. 150. 50.
arc 1 10 150. 150. 50. -90. 0.
line 1 30 200. 150. 250. 150.
arc 1 10 150. 150. 50. 0. 90.
line 1 30 150. 200. 150. 250.
arc 1 20 150. 150. 75. 0. -90.
arc 1 20 150. 150. 75. 90. 0.
arc 1 10 150. 150. 50. 90. 180.
wp 11
0 98. 150.
1 148. 100.4
2 150. 77.
2 150. 52.
3 199.9 148.
4 223. 150.
4 248. 150.
5 152. 199.9
6 150. 223.
6 150. 248.
8 224.8 153.
7 153. 75.2
tl 4
2 145. 85. 5 3 5 3
7 165. 70.9 5 3 5 8
4 215. 145. 5 3 5 3
8 218.5 164.9 5 3 5 8
st 4
2 0 150. 85.
7 1 165. 76.5
4 2 215. 150.
8 3 223.5 164.9
obst 0
iti 12
go 20.
turn -90.
go 10.
go 10.
go 10.
turn -90.
go 25.
turn -90.
go 10.
turn 90.
go 20.
stop 0.
end

12
assets/08.iti Normal file
View File

@@ -0,0 +1,12 @@
go 10.
turn -90.
go 30.
turn 90.
go 20.
go 10.
turn -90.
go 20.
turn 90.
go 25.
go 20.
stop 0.

72
assets/08.map Normal file
View File

@@ -0,0 +1,72 @@
map "nycity"
graphics "map_08_nycity.bmp"
guide "b-08.bmp"
init 20. 250. 0.
rd 20
line 1 30 5. 250. 50. 250.
line 1 30 50. 250. 150. 250.
line 1 30 150. 250. 200. 250.
line 1 20 50. 250. 50. 150.
line 1 20 150. 250. 150. 150.
line 1 20 200. 250. 200. 150.
line 1 30 50. 150. 150. 150.
line 1 30 150. 150. 200. 150.
line 1 20 50. 150. 50. 50.
line 1 20 150. 150. 150. 50.
line 1 20 200. 150. 200. 50.
line 1 30 50. 50. 150. 50.
line 1 30 150. 50. 200. 50.
line 1 30 250. 50. 275. 50.
line 1 30 200. 250. 250. 250.
line 1 20 250. 250. 250. 150.
line 1 30 200. 150. 250. 150.
line 1 20 250. 150. 250. 100.
line 1 20 250. 150. 250. 50.
line 1 30 200. 50. 250. 50.
wp 20
0 48. 250.
1 148. 250.
2 198. 250.
3 50. 152.
4 150. 152.
5 200. 152.
6 148. 150.
7 198. 150.
8 50. 52.
9 150. 52.
10 200. 52.
11 148. 50.
12 198. 50.
13 273. 50.
14 248. 250.
15 250. 152.
16 248. 150.
17 250. 102.
18 250. 52.
19 248. 50.
tl 0
st 0
obst 0
iti 12
go 10.
turn -90.
go 25.
turn 90.
go 20.
go 10.
turn -90.
go 20.
turn 90.
go 25.
go 20.
stop 0.
end

14
assets/09.iti Normal file
View File

@@ -0,0 +1,14 @@
go 20.
go 20.
go 20.
go 20.
turn -90.
go 10.
go 20.
turn -90.
go 10.
turn 30.
go 20.
turn 100.
go 10.
stop 0.

105
assets/09.map Normal file
View File

@@ -0,0 +1,105 @@
map "paris"
graphics "map_09_paris.bmp"
guide "b-09.bmp"
init 40. 275. 0.
rd 31
line 1 30 25. 275. 100. 275.
line 1 20 100. 275. 175. 275.
line 1 30 175. 275. 250. 275.
line 1 20 250. 275. 400. 275.
line 1 30 400. 275. 475. 275.
line 1 20 50. 225. 25. 275.
line 1 20 100. 275. 100. 225.
line 1 20 175. 275. 175. 225.
line 1 20 250. 275. 250. 225.
line 1 20 400. 275. 400. 175.
line 1 30 100. 225. 50. 225.
line 1 30 175. 225. 100. 225.
line 1 20 250. 225. 175. 225.
line 1 20 400. 175. 250. 225.
line 1 30 475. 175. 400. 175.
line 1 20 50. 225. 175. 100.
line 1 30 100. 225. 100. 175.
line 1 30 175. 225. 175. 100.
line 1 30 250. 225. 250. 100.
line 1 30 400. 175. 400. 100.
line 1 20 250. 100. 175. 100.
line 1 20 400. 100. 250. 100.
line 1 30 450. 100. 400. 100.
line 1 20 175. 100. 225. 50.
line 1 20 325. 100. 225. 50.
line 1 20 400. 100. 400. 75.
line 1 20 400. 75. 325. 50.
line 1 20 400. 75. 450. 25.
line 1 30 325. 50. 225. 50.
line 1 10 225. 50. 175. 25.
line 1 10 225. 50. 250. 25.
wp 32
0 98. 275.
1 173. 275.
2 248. 275.
3 398. 275.
4 473. 275.
5 23. 273.
6 100. 227.
7 175. 227.
8 250. 227.
9 400. 177.
10 52. 225.
11 102. 225.
12 177. 225.
13 260. 223.
14 402. 175.
15 173. 102.
16 100. 177.
17 175. 102.
18 250. 102.
19 400. 102.
20 177. 100.
21 252. 100.
21 327. 100.
22 402. 100.
23 223. 52.
24 227. 51.
25 400. 77.
26 340. 55.
27 448. 27.
28 235. 50.
29 187. 30.
30 240. 35.
tl 6
15 165. 105. 5 3 5 3
17 170. 115. 5 3 5 8
20 185. 105. 5 3 5 13
23 215. 55. 5 3 5 3
24 240. 60. 5 3 5 8
28 240. 53. 5 3 5 13
st 6
15 0 165. 110.
17 1 175. 115.
20 2 185. 100.
23 3 215. 60.
24 4 245. 60.
28 5 240. 50.
obst 0
iti 14
go 20.
go 20.
go 20.
go 20.
turn -90.
go 10.
go 20.
turn -90.
go 10.
turn 30.
go 20.
turn 100.
go 10.
stop 0.
end

20
assets/11.iti Normal file
View File

@@ -0,0 +1,20 @@
go 30.
turn 90.
go 30.
turn 45.
go 30.
turn -45.
go 30.
turn -70.
go 20.
turn 120.
go 20.
turn -110.
go 20.
turn -45.
go 30.
turn -45.
go 30.
turn 135.
go 20.
stop 0.

40
assets/11.map Normal file
View File

@@ -0,0 +1,40 @@
map "hamburg"
rd 14
line 1 20 15. 270. 30. 210.
arc 1 20 120. 210. 90. 180. 270.
line 1 20 120. 120. 60. 60.
line 1 20 60. 60. 15. 60.
line 1 20 120. 120. 300. 90.
line 1 20 300. 90. 480. 120.
arc 1 20 360. 120. 120. 0. 90.
line 1 20 360. 240. 240. 240.
arc 1 20 240. 120. 120. 90. 180.
line 1 20 240. 240. 120. 120.
arc 1 20 360. 150. 90. 90. 180.
line 1 20 270. 150. 300. 90.
line 1 20 410. 280. 360. 240.
line 1 20 480. 120. 585. 120.
wp 11
1 118. 120.9
2 62. 62.
3 20. 60.
5 478. 119.3
6 362. 239.1
7 242. 240.
8 120.9 122.
9 122. 122.
11 299. 92.
12 362. 241.6
13 570. 120.
tl 1
12 365. 248. 5 3 5 7
st 1
12 0 370. 248.
end

21
assets/12.iti Normal file
View File

@@ -0,0 +1,21 @@
go 30.
go 20.
turn -45.
go 30.
turn -45.
go 30.
turn -90.
go 30.
turn -60.
go 20.
turn 120.
go 20.
turn -110.
go 20.
turn -45.
go 30.
turn -45.
go 30.
turn 135.
go 20.
stop 0.

42
assets/12.map Normal file
View File

@@ -0,0 +1,42 @@
map "PRG"
rd 14
line 1 30 585. 60. 480. 120.
line 1 30 480. 120. 420. 180.
line 1 20 420. 180. 300. 240.
line 1 20 300. 240. 300. 120.
line 1 20 300. 120. 180. 120.
line 1 20 300. 240. 180. 240.
line 1 20 180. 120. 180. 240.
line 1 20 180. 120. 120. 60.
line 1 20 180. 30. 120. 60.
line 1 20 120. 60. 60. 120.
arc 1 10 180. 120. 120. 90. 180.
line 1 20 60. 120. 15. 30.
line 1 20 180. 240. 180. 290.
line 1 20 300. 290. 300. 240.
wp 11
2 302. 238.5
3 300. 122.
4 182. 120.
5 182. 240.
6 180. 238.
7 122. 62.
8 122. 59.
9 62. 118.
11 20. 40.
12 180. 280.
13 300. 242.
tl 2
2 310. 240. 5 3 5 7
13 295. 250. 8 3 5 7
st 2
2 0 310. 235.
13 1 300. 250.
end

12
assets/13.iti Normal file
View File

@@ -0,0 +1,12 @@
go 20.
turn 15.
go 20.
turn 90.
go 20.
go 20.
turn 45.
go 20.
go 20.
turn -45.
go 20.
stop.

52
assets/13.map Normal file
View File

@@ -0,0 +1,52 @@
map "PRD"
rd 18
line 1 20 300.0 60.0 300.0 15.0
line 1 20 180.0 15.0 180.0 60.0
line 1 20 300.0 60.0 585.0 60.0
line 1 20 30.0 20.0 120.0 180.0
line 1 20 180.0 60.0 120.0 60.0
line 1 20 180.0 60.0 300.0 60.0
line 1 20 300.0 60.0 300.0 120.0
line 1 20 120.0 180.0 300.0 60.0
line 1 20 300.0 120.0 480.0 240.0
line 1 20 300.0 120.0 210.0 180.0
line 1 20 210.0 180.0 120.0 180.0
line 1 20 15.0 180.0 120.0 180.0
line 1 20 120.0 60.0 120.0 180.0
line 1 20 70.0 280.0 120.0 180.0
line 1 20 120.0 180.0 120.0 280.0
line 1 20 120.0 180.0 210.0 240.0
line 1 20 210.0 240.0 480.0 240.0
line 1 20 480.0 240.0 585.0 240.0
wp 16
0 300. 20.
1 180. 56.
2 570. 60.
3 117.75 176.
4 124. 60.
5 296. 60.
6 300. 116.
7 297. 62.
8 477 238.
10 124. 180.
11 116. 180.
12 120. 176.
13 118. 184.
14 120. 260.
15 206. 238.
17 570. 240.
tl 1
16 465. 235. 5 3 5 7
st 1
16 0 465. 240.
end

12
assets/14.iti Normal file
View File

@@ -0,0 +1,12 @@
go 30.
turn 120.
go 20.
turn -90.
go 20.
turn 45.
go 20.
turn -90.
go 20.
turn 130.
go 20.
stop.

61
assets/14.map Normal file
View File

@@ -0,0 +1,61 @@
map "seine"
rd 22
line 1 20 420. 10. 300. 70.
line 1 20 300. 70. 180. 70.
line 1 20 180. 70. 100. 10.
line 1 20 300. 70. 300. 10.
line 1 20 180. 70. 180. 10.
line 1 20 300. 70. 300. 120.
line 1 20 180. 70. 180. 120.
line 1 20 580. 30. 300. 120.
line 1 20 300. 120. 180. 120.
line 1 20 180. 120. 120. 120.
line 1 20 120. 120. 120. 240.
line 1 20 120. 240. 300. 120.
line 1 20 210. 240. 120. 240.
line 1 20 300. 180. 210. 240.
line 1 20 300. 120. 300. 180.
line 1 20 300. 180. 500. 280.
line 1 20 120. 240. 160. 280.
line 1 20 100. 280. 120. 240.
line 1 20 20. 240. 120. 240.
line 1 20 20. 40. 120. 240.
line 1 20 120. 240. 120. 280.
line 1 20 120. 120. 20. 40.
wp 20
0 304. 67.
1 176. 70.
2 108. 16.
3 300. 20.
4 180. 20.
5 300. 116.
6 180. 116.
7 304. 118.
9 124. 120.
10 210. 236.
11 297. 122.
12 124. 240.
14 300. 176.
15 490. 275.
16 155. 275.
17 118. 244.
18 116. 240.
19 118. 236.
20 120. 270.
21 30. 48.
tl 2
5 295. 110. 5 3 5 8
11 285. 125. 5 3 5 13
st 2
5 0 300. 110.
11 1 285. 130.
end

8
assets/15.iti Normal file
View File

@@ -0,0 +1,8 @@
go 20.
go 30.
go 10.
turn -15.
go 20.
turn 75.
stop 0.

47
assets/15.map Normal file
View File

@@ -0,0 +1,47 @@
map "scade"
rd 22
line 1 30 20. 20. 70. 20.
arc 1 20 70. 80. 60. -90. 90.
arc 1 20 70. 200. 60. 270. 90.
line 1 30 70. 260. 200. 260.
line 1 30 200. 260. 300. 260.
line 1 30 200. 240. 300. 240.
arc 1 20 200. 210. 50. 180. 90.
arc 1 20 200. 210. 30. 180. 90.
line 1 30 150. 110. 150. 210.
line 1 30 170. 110. 170. 210.
arc 1 20 200. 110. 50. 270. 180.
arc 1 20 200. 110. 30. 270. 180.
line 1 30 250. 60. 200. 60.
line 1 30 250. 80. 200. 80.
arc 1 20 300. 210. 50. 90. 0.
arc 1 20 300. 210. 30. 90. 0.
line 1 30 350. 210. 413.3 20.
line 1 30 330. 210. 380. 60.
arc 1 30 350. 140. 120. 90. -50.
line 1 30 300. 260. 550. 260.
line 1 30 413.3 20. 550. 20.
line 1 30 470. 140. 550. 140.
wp 11
3 115. 260.
4 290. 260.
16 412.3 23.
17 372. 84.
18 469.9 142.5
18 434.85 56.15
19 305. 260.
19 359. 260.
19 520. 260.
20 520. 20.
21 520. 140.
tl 0
st 0
end

10
assets/16.iti Normal file
View File

@@ -0,0 +1,10 @@
go 20.
turn -34.
go 30.
turn 146.
go 20.
turn -56.
go 30.
turn -34.
go 20.
stop 0.

15
assets/17.iti Normal file
View File

@@ -0,0 +1,15 @@
go 20.
turn 47.
go 20.
turn -90.
go 20.
turn 90.
go 20.
turn 124.
go 30.
turn 124.
go 20.
turn -60.
go 30.
stop 0.

8
assets/18.iti Normal file
View File

@@ -0,0 +1,8 @@
go 20.
turn -34.
go 30.
turn -146.
go 20.
turn -51.
go 20.
stop 0.

BIN
assets/b-00.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-01.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-02.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-03.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-04.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-05.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-06.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-07.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-08.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/b-09.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/collision.wav Normal file

Binary file not shown.

BIN
assets/ctl_10.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/ctl_11.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/ctl_12.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/ctl_13.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/ctl_14.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/direction.wav Normal file

Binary file not shown.

BIN
assets/exit.wav Normal file

Binary file not shown.

BIN
assets/game_10.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/game_11.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 KiB

BIN
assets/game_12.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/game_13.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/game_14.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

BIN
assets/light.wav Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/map_03_oneway_ea.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/map_08_nycity.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/map_09_paris.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 KiB

BIN
assets/obst.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
assets/orange.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
assets/speed.wav Normal file

Binary file not shown.

View File

@@ -1,2 +0,0 @@
Le [journal](journal.org) contient un bref résumé de notre progression à travers
les notes de cours, ainsi que quelques informations logistiques.

44
cours/audio/Makefile Normal file
View File

@@ -0,0 +1,44 @@
HEPTC=heptc
HEPTLIB=$(shell heptc -where)
CC=gcc
CFLAGS=-g $(shell pkg-config --cflags --libs sdl2 sndfile) -I$(HEPTLIB)/c -lm
PYGMENTS=python -m pygments -x
TARGET=audio
SOURCES=audio_c/audio_types.c \
audio_c/audio.c \
buffer.c \
vcd_lib.c \
mathext.c \
vcd.c \
main.c
.PHONY: all clean test
all: $(TARGET) audio.html main.html
%.html: %.ept
$(PYGMENTS) -l ../../../notes/heptagon.py:HeptagonLexer -O full -o $@ $^
%.html: %.c
$(PYGMENTS) -O full -o $@ $^
clean:
rm -f $(TARGET) *.{epci,log,mls,obc,html} $(TARGET).{pdf,tex}
rm -rf audio_c
test: $(TARGET)
./$(TARGET)
$(TARGET): $(SOURCES)
@pkg-config --exists sdl2 || \
( echo "La bibliothèque SDL2 est absente."; exit 1 )
@pkg-config --exists sndfile || \
( echo "La bibliothèque sndfile est absente."; exit 1 )
$(CC) $(CFLAGS) -o $@ -I audio_c -I. $^
audio_c/audio_types.c audio_c/audio.c: audio.ept main.c mathext.epci vcd.epci
$(HEPTC) -target c $<
%.epci: %.epi
$(HEPTC) $<

14
cours/audio/README.md Normal file
View File

@@ -0,0 +1,14 @@
# Synthèse sonore élémentaire en Heptagon
Ce dossier contient quelques noeuds Heptagon élementaires qui produisent du son.
Il utilise les bibliothèques SDL2 et sndfile. Elles doivent être installées via
le gestionnaire de paquet de votre système d'exploitation (`apt-get` sous
GNU/Linux Debian ou Ubuntu, `pacman` sous Arch Linux, `brew` sous macOS, etc.).
```shell
$ make
$ ./audio
```
Pour essayer différents codes, il faut éditer le noeud `main` dans `audio.ept`.

515
cours/audio/audio.ept Normal file
View File

@@ -0,0 +1,515 @@
(******************************************************************************)
(* SYNTHÈSE SONORE ÉLÉMENTAIRE EN HEPTAGON *)
(******************************************************************************)
(* Le but de ce fichier est de démontrer quelques techniques élémentaires de
génération de son en Heptagon, à travers de modestes expérimentations. Il n'a
bien sûr pas vocation à se substituer à un cours de traitement du signal ou
d'acoustique. En revanche, il peut facilement servir d'illustration de
diverses techniques de programmation en Heptagon. *)
(* Le flot d'échantillons sonores produits par ce programme synchrone est
branché à un petit bout de code C qui les envoie au système sonore de votre
système d'exploitation par le biais de la bibliothèque SDL2. Votre OS les
transmet à la carte son qui elle même les envoie à vos enceintes, casque ou
écouteurs. *)
(* Les langages synchrones ont été utilisés pour la synthèse sonore. Si ce sujet
vous intéresse, vous pouvez par exemple consulter la page du langage Faust, à
la syntaxe rudimentaire mais aux bibliothèques acoustiques, sonores et
musicales très développées : http://faust.grame.fr *)
(* On va utiliser une petite bibliothèque de composants mathématiques. Les
curieuses et curieux pourront aller voir mathext.epci. *)
open Mathext
(* Avant de commencer, on a besoin de quelques définitions et outils. *)
(* Le nombre d'échantillons, c'est à dire ici de pas synchrones, que le système
sonore va consommer une seconde. *)
const period : int = 44100
(* Un signal mono est un simple flot de nombres à virgule flottante. *)
type mono = float
(* Un signal stéréo fournit deux échantillons, gauche et droit, la carte son se
chargeant de les mixer pour donner l'impression d'un son 'surround'. *)
type stereo = { l : float; r : float }
(* Le signal constant silencieux. *)
const silence : stereo = { l = 0.0; r = 0.0 }
(* On peut dupliquer un signal mono pour obtenir un signal stéréo
inintéressant, les deux canaux portant la même valeur. *)
fun stereo_of_mono(a : mono) returns (o : stereo)
let
o = { l = a; r = a }
tel
(* On peut appliquer un gain à un signal stéréo, c'est à dire le multiplier par
un flottant pour l'amener à une amplitude différente. *)
fun stereo_gain(g : float; s : stereo) returns (o : stereo)
let
o = { l = g *. s.l; r = g *. s.r };
tel
(* Étant donné deux signaux, on peut les combiner via leur somme. *)
fun stereo_sum(s1, s2 : stereo) returns (o : stereo)
let
o = { l = s1.l +. s2.l; r = s1.r +. s2.r }
tel
(* Quand on utilise les deux fonctions qu'on vient de définir, gare à
l'amplitude en sortie ! Une amplitude trop élevée risque de dépasser la
capacité de votre carte son, enceintes ou écouteurs, ce qui cause un
phénomène de saturation : tous les échantillons d'amplitude trop élevée sont
écrasés sur l'amplitude maximale. *)
(* La fonction mix ci-dessous pallie le défaut de la fonction stereo_sum en
renormalisant le résultat. De plus, elle traite un tableau de signaux, et
donc moralement un nombre d'entrées arbitraires. *)
fun stereo_mix<<n : int>>(s : stereo^n) returns (o : stereo)
let
o = stereo_gain(1.0 /. float(n), fold<<n>> stereo_sum(s, silence));
tel
(* On peut commencer à écouter un peu de son, par exemple celui du silence. *)
node main0() returns (o : stereo)
let
o = silence;
tel
(* Quid du noeud suivant ? *)
node cracks() returns (o : stereo)
let
o = { l = 4200.0; r = 4200.0 };
tel
(* On entendu un craquement, puis plus rien, puis un craquement lorsqu'on
interromp le programme. Pourquoi ?
Physiquement, le son est une vibration produit par une onde acoustique, c'est
à dire une oscillation de la pression de l'air. Autrement dit, il s'agit
d'une *variation*. Donc, le signal constant ne peut pas donner lieu à un son,
sauf au premier instant (passage de 0 à 4200) puis lorsqu'on interromp le
programme (passage de 4200 à 0).
Et si on essayait un signal qui varie ? Par exemple, un signal carré qui
passe de 1 à 0 toutes les demi-secondes. *)
node periodic(p : int) returns (o : int)
var n : int;
let
o = 0 fby (if n = p then 0 else n);
n = o + 1;
tel
node beats_1() returns (o : stereo)
let
o = stereo_of_mono(if periodic(period) <= period / 2 then 1.0 else -. 1.0);
tel
(* On obtient une série de battements simples. Faire en sorte que le canal droit
soit l'opposé du canal gauche produit un effet intéressant. *)
node beats_2() returns (o : stereo)
var l : float;
let
l = if periodic(period) <= period / 2 then 1.0 else -. 1.0;
o = { l = l; r = -. l };
tel
(* Essayons maintenant de générer un signal qui croît indéfiniment. *)
node fcnt(ini : float; step : float) returns (o : float)
let
o = ini fby (o +. step);
tel
node sawtooth_1() returns (o : stereo)
let
o = stereo_of_mono(fcnt(0.0, 1.0));
tel
(* On entend quelques craquements, puis plus rien. Normal : ce signal n'oscille
pas vraiment, ou du moins pas avant d'atteindre l'overflow. Pourquoi ne pas
tester un signal périodique en dents de scie, dans ce cas ? *)
node sawtooth_2() returns (o : stereo)
var t : float;
let
t = float(periodic(128));
o = stereo_of_mono(t);
tel
(* Tiens, un son à peu près constant ! Pas très harmonieux cependant. *)
(* Est-ce qu'appliquer un gain ferait une différence ? Pour bien observer la
différence, on n'a qu'à faire passer le gain de 0 à 1 à chaque seconde.
C'est très facile à programmer en Heptagon. *)
node sawtooth_3() returns (o : stereo)
var t : float; g : float;
let
t = float(periodic(128));
g = float(periodic(period)) /. float(period);
o = stereo_gain(g, stereo_of_mono(t));
tel
(* On entend nettement le signal en dent de scie, avec un pic à la fin de la
seconde. De façon intéressante, si on augmente le gain, le son apparaît comme
plus pincé, un peu comme les notes d'une guitare. *)
node sawtooth_4() returns (o : stereo)
var t : float; g : float;
let
t = float(periodic(128));
g = 3.0 *. float(periodic(period)) /. float(period);
o = stereo_gain(g, stereo_of_mono(t));
tel
(* En augmentant la période, les pics s'éloignent, en la diminuant, les
pics se rapprochent. *)
node period_per_sec(a : int) returns (o : float)
let
o = float(periodic(period / a)) /. float(period / a);
tel
node sawtooth_5() returns (o : stereo)
var t : float; g : float;
let
t = float(periodic(128));
g = period_per_sec(2);
o = stereo_gain(g, stereo_of_mono(t));
tel
(* On peut aussi appliquer des gains différents sur le canal mono et stéréo. *)
node every_sec(s : int) returns (c : bool)
let
c = periodic(period * s) = ((- 1) fby 0);
tel
node sawtooth_6() returns (o : stereo)
var t : float; g1, g2 : float;
let
t = float(periodic(128));
o = { l = g1 *. t; r = g2 *. t };
automaton
state FastLeftSlowRight
do g1 = period_per_sec(1);
g2 = period_per_sec(8);
until every_sec(5) then SlowLeftFastRight
state SlowLeftFastRight
do g1 = period_per_sec(5);
g2 = period_per_sec(1);
until every_sec(5) then FastLeftSlowRight
end
tel
(* Tous ces sons ne sont pas très harmonieux. Peut-on en obtenir de plus purs ?
Le traitement du signal nous enseigne, via la théorie de la transformée de
Fourier, que tout signal raisonnablement régulier peut se décomposer en une
somme (infinie) de sinusoïde. Autrement dit, les signaux sinusoïdaux peuvent
servir de briques de base élémentaires mais universelles. Considérés comme
des signaux audio, ils forment des tons purs, élémentaires.
*)
node pure_tone(p : float) returns (o : float)
var t : float;
let
t = fcnt(0.0, 1.0);
o = sin(t *. (p /. float(period)) *. 2.0 *. Mathext.pi);
tel
(* Par exemple, la sinusoïde de fréquence 440.1 Hz, communément désignée sous le
nom de La 440, devrait vous être familière. *)
node main_pure_1() returns (o : stereo)
let
o = stereo_of_mono(pure_tone(440.0));
tel
(* En plus d'être la tonalité du téléphone, elle sert de référence pour
l'accordage des pianos, violons et d'autres instruments.
https://fr.wikipedia.org/wiki/La_440 *)
(* En mélangeant plusieurs sinusoïdes ensembles, on peut obtenir des effets
rétro assez amusants. *)
node some_pure_tone(p : float; i : int) returns (s : stereo)
let
s = stereo_gain(period_per_sec(i + 1), stereo_of_mono(pure_tone(p)));
tel
node oscillating_counter<<m : int>>(i : int) returns (last o : int = 0)
var step : int;
let
step = if every_sec(1) then 1 else 0;
automaton
state Init
do o = i
until true then Increase
state Increase
do o = last o + step
until o >= m then Decrease
state Decrease
do o = last o - step
until o <= 0 then Increase
end
tel
node main_pure_2() returns (o : stereo)
var periods : float^3; speeds : int^3;
let
periods = [440.0, 261.6256, 4186.009];
speeds = map<<3>>(oscillating_counter<<10>>)([1, 3, 7]);
o = stereo_mix<<3>>(map<<3>> some_pure_tone(periods, speeds));
tel
(* Enfin, les amatrices et amateurs de piano pourront trouver sur la page
https://en.wikipedia.org/wiki/Piano_key_frequencies
une formule associant une fréquence de sinusoïde à une note de piano. On peut
l'utiliser comme suit. *)
fun piano_freq_of_key(k : int) returns (f : float)
let
f = Mathext.pow(2.0, (Mathext.float(k) -. 49.0) /. 12.0) *. 440.0;
tel
node tone_of_piano_key(k : int) returns (o : stereo)
let
o = stereo_of_mono(pure_tone(piano_freq_of_key(k)));
tel
node maintain(c : bool; x : int on c; ini : int) returns (o : int)
let
o = merge c x ((ini fby o) whenot c);
tel
node main_pure_3() returns (o : stereo)
var k : int; c : bool;
let
o = tone_of_piano_key(k);
k = maintain(c, 40 + periodic(53 - 40), 40);
c = periodic(period) = 0;
tel
(* On peut essayer de programmer un piano midi. *)
(* Pour générer des transitions propres entre les notes, on a besoin de modifier
nos tons à travers une "enveloppe". La plus classique est l'enveloppe dite
"Attack-Decay-Sustain-Release", cf. Wikipédia.
https://en.wikipedia.org/wiki/Envelope_(music)#ADSR
Le noeud ci-dessous produit une telle enveloppe périodiquement, tous les t
instants. L'enveloppe prend la forme d'un gain entre 0 et 1.
Les paramètres a, d et s doivent-être tels que 0.0 < a + d + s < 1.0. Ils
expriment la fraction de t correspondant à chacune des quatre phases, la
phase d étant la fraction de t définie comme 1 - a - d - s.
Le paramètre s_level est le niveau de la phase S, entre 0 et 1 donc.
*)
node adsr_envelope(t : int; a, d, s : float; s_level : float)
returns (e : float)
var c, a_stop, d_stop, s_stop : int;
let
a_stop = int(float(t) *. a);
d_stop = a_stop + int(float(t) *. d);
s_stop = d_stop + int(float(t) *. s);
c = periodic(t);
automaton
state Attack
do e = float(c) /. float(a_stop);
unless c >= a_stop continue Decay
state Decay
var f : float;
do e = 1.0 -. (1.0 -. s_level) *. f;
f = float(c - a_stop) /. float(d_stop - a_stop);
unless c >= d_stop continue Sustain
state Sustain
do e = s_level;
unless c >= s_stop continue Release
state Release
do e = s_level *. (1.0 -. float(c - s_stop) /. float(t - s_stop));
until c + 1 >= t continue Attack
end
tel
node midi_piano<<n : int>>(keys : int^2^n; time : int^n) returns (o : stereo)
var i, j : int; next : bool; duree_mesure : int; e : float;
let
duree_mesure = 2 * period; (* 1 mesure = 8 noires = 4 sec à 120 BPM. *)
i = periodic(n);
j = maintain(next, i, 0);
o = stereo_gain(e, stereo_mix<<2>>(map<<2>> tone_of_piano_key(keys[>j<])));
e = adsr_envelope(duree_mesure / time[> j <], 0.3, 0.1, 0.4, 0.5);
automaton
state Next
do next = true
until true then Wait
state Wait
var c : int;
do next = false;
c = 0 fby (c + 1);
until c >= (duree_mesure / time[> j <]) then Next
end
tel
const num_keys : int = 82
node main_pure_4() returns (o : stereo)
var keys : int^2^num_keys; time : int^num_keys;
let
keys = [
[44, 00], [37, 00], [40, 00], [42, 00],
[44, 00], [37, 00], [40, 00], [42, 00],
[44, 00], [37, 00], [40, 00], [42, 00],
[44, 00], [37, 00], [40, 00], [42, 00],
[44, 00], [37, 00], [41, 00], [42, 00],
[44, 00], [37, 00], [41, 00], [42, 00],
[44, 00], [37, 00], [41, 00], [42, 00],
[44, 00], [37, 00], [41, 00], [42, 00],
[44, 00],
[37, 00],
[40, 37], [42, 00], [44, 00],
[37, 00], [40, 00], [42, 00],
[35, 39], [32, 00], [35, 00], [37, 00],
[39, 00], [32, 00], [35, 00], [37, 00],
[35, 39], [32, 00], [35, 00], [37, 00],
[39, 00], [32, 00], [35, 00],
[42, 00],
[35, 00],
[35, 40], [39, 00], [42, 00],
[35, 00], [40, 00], [39, 00],
[33, 37], [30, 00], [33, 00], [35, 00],
[33, 00], [30, 00], [33, 00], [35, 00],
[33, 37], [30, 00], [33, 00], [35, 00],
[37, 00], [30, 00], [33, 00],
[0, 0], [0, 0], [0, 0], [0, 0] (* silence *)
];
time = [
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
2,
2,
8, 8, 2,
2, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 4,
2,
2,
8, 8, 2,
2, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 8, 8,
4, 4, 4,
1, 1, 1, 1 (* silence *)
];
o = midi_piano<<num_keys>>(keys, time);
tel
(* Bonus : la méthode de Karplus-Strong pour la synthèse de son de guitare.
https://en.wikipedia.org/wiki/Karplus%E2%80%93Strong_string_synthesis
http://sites.music.columbia.edu/cmc/MusicAndComputers/chapter4/04_09.php
*)
node flip(i: int) returns (o: float)
let
o = if (i % 2 = 0) then 1.0 else -.1.0
tel
node karplus_strong<<l:int>>() returns (y : float)
var b : float^l; i: int;
let
i = 0 fby ((i+1) % l);
y = 0.5 *. (b[>i<] +. 0.0 fby y);
b = (mapi<<l>> flip ()) fby ([b with [i] = y]);
tel
node repeat<<n : int>>(x : stereo) returns (o : stereo)
var last t : stereo^n = silence^n;
let
automaton
state Fill
do o = x;
t = [ last t with [ periodic(n) ] = x ]
until periodic(n) = n - 1 then Repeat
state Repeat
do o = t[> periodic(n) <]
end
tel
node saturating_counter(max : int) returns (o : int)
var c : int;
let
c = 0 fby (c + 1);
o = if c < max then c else max;
tel
node main_kp() returns (o : stereo)
var s : stereo;
let
s = repeat<<period>>({ l = karplus_strong<<115>>();
r = karplus_strong<<55>>() });
o = stereo_gain(float(saturating_counter(5 * period)) /. float(5 * period),
s);
tel
(* Le noeud principal du programme. *)
(* Vous pouvez choisir un des noeuds principaux main_XXX écrits ci-dessus, ou
bien écrire le votre. *)
node main() returns (o : stereo)
let
o = main_pure_4();
tel

61
cours/audio/buffer.c Normal file
View File

@@ -0,0 +1,61 @@
#include "buffer.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max(a, b) ((a) <= (b) ? (a) : (b))
void *malloc_checked(size_t size) {
void *result = malloc(size);
if (!result) {
perror("malloc()");
exit(EXIT_FAILURE);
}
return result;
}
char *strdup_checked(const char *s) {
char *result = strdup(s);
if (!result) {
perror("strdup()");
exit(EXIT_FAILURE);
}
return result;
}
buffer_t *buffer_alloc(size_t initial_size) {
buffer_t *buff = malloc_checked(sizeof *buff);
buff->data = malloc_checked(initial_size * sizeof *buff->data);
buff->size = initial_size;
buff->occupancy = 0;
return buff;
}
void buffer_free(buffer_t *buffer) {
assert (buffer);
free(buffer->data);
free(buffer);
}
void buffer_resize(buffer_t *buff, size_t new_size) {
assert (buff);
assert (new_size >= buff->size);
unsigned char *new_data = malloc_checked(new_size);
memcpy(new_data, buff->data, buff->occupancy);
free(buff->data);
buff->data = new_data;
buff->size = new_size;
}
void buffer_write(buffer_t *buff, void *data, size_t data_size) {
assert (buff);
if (buff->occupancy + data_size > buff->size)
buffer_resize(buff, max(buff->size + data_size, 2 * buff->size));
memcpy(buff->data + buff->occupancy, data, data_size);
buff->occupancy += data_size;
}

27
cours/audio/buffer.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef BUFFER_H
#define BUFFER_H
#include <sys/types.h>
/* A simple type of append-only buffers. */
typedef struct buffer {
unsigned char *data;
size_t size;
size_t occupancy;
} buffer_t;
void *malloc_checked(size_t size);
char *strdup_checked(const char *);
buffer_t *buffer_alloc(size_t initial_size);
void buffer_free(buffer_t *buff);
void buffer_write(buffer_t *buff, void *data, size_t data_size);
#define buffer_foreach(ty, var, buffer) \
for (ty *var = (ty *)buffer->data; \
var < (ty *)(buffer->data + buffer->occupancy); \
var++)
#endif /* BUFFER_H */

52
cours/audio/hept_ffi.h Normal file
View File

@@ -0,0 +1,52 @@
#ifndef HEPT_FFI_H
#define HEPT_FFI_H
#define UNPAREN(...) __VA_ARGS__
#define DECLARE_HEPT_FUN(module, name, inputs, outputs) \
typedef struct { outputs; } module ## __ ## name ## _out; \
void module ## __ ## name ##_step(UNPAREN inputs, \
module ## __ ## name ## _out *)
#define DECLARE_HEPT_FUN_NULLARY(module, name, outputs) \
typedef struct { outputs; } module ## __ ## name ## _out; \
void module ## __ ## name ##_step(module ## __ ## name ## _out *)
#define DEFINE_HEPT_FUN(module, name, inputs) \
void module ## __ ## name ##_step(UNPAREN inputs, \
module ## __ ## name ## _out *out)
#define DEFINE_HEPT_FUN_NULLARY(module, name, inputs) \
void module ## __ ## name ##_step(module ## __ ## name ## _out *out)
#define DECLARE_HEPT_NODE(module, name, inputs, outputs, state) \
typedef struct { outputs; } module ## __ ## name ## _out; \
typedef struct { state; } module ## __ ## name ## _mem; \
void module ## __ ## name ##_step(UNPAREN inputs, \
module ## __ ## name ## _out *, \
module ## __ ## name ## _mem *); \
void module ## __ ## name ##_reset(module ## __ ## name ## _mem *)
#define DECLARE_HEPT_NODE_NULLARY(module, name, outputs, state) \
typedef struct { outputs; } module ## __ ## name ## _out; \
typedef struct { state; } module ## __ ## name ## _mem; \
void module ## __ ## name ##_step(module ## __ ## name ## _out *, \
module ## __ ## name ## _mem *); \
void module ## __ ## name ##_reset(module ## __ ## name ## _mem *)
#define DEFINE_HEPT_NODE_RESET(module, name) \
void module ## __ ## name ##_reset(module ## __ ## name ## _mem *mem)
#define DEFINE_HEPT_NODE_STEP(module, name, inputs) \
void module ## __ ## name ##_step(UNPAREN inputs, \
module ## __ ## name ## _out *out, \
module ## __ ## name ## _mem *mem)
#define DEFINE_HEPT_NODE_NULLARY_STEP(module, name, inputs) \
void module ## __ ## name ##_step(module ## __ ## name ## _out *out, \
module ## __ ## name ## _mem *mem)
/* FIXME remove when Heptagon's pervasives.h has been fixed. */
typedef char * string;
#endif /* HEPT_FFI */

153
cours/audio/main.c Normal file
View File

@@ -0,0 +1,153 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <SDL2/SDL.h>
#include <sndfile.h>
#include "audio.h"
#include "vcd.h"
const size_t sample_rate = Audio__period;
void die(const char *message) {
fprintf(stderr, message);
exit(EXIT_FAILURE);
}
SNDFILE *file_out = NULL;
int main(int argc, char** argv)
{
Audio__main_mem mem;
Audio__main_out res;
SDL_AudioSpec spec;
SDL_AudioDeviceID dev;
int opt = -1;
bool quiet = false;
size_t max_sec = SIZE_MAX; /* largest value of type size_t */
const char *filename = NULL;
Uint32 buffered;
while ((opt = getopt(argc, argv, "ho:qm:t:")) != -1) {
switch (opt) {
case 'h':
printf("Usage: %s OPTIONS\n", argv[0]);
printf("Options:\n");
printf(" -o <file.wav> write samples to <file.wav>\n");
printf(" -q do not play sound\n");
printf(" -m <sec> play for <sec> seconds\n");
printf(" -t <file.vcd> dump traces in <file.vcd>\n");
printf(" -h display this message\n");
return 0;
case 'q':
quiet = true;
break;
case 'o':
filename = optarg;
break;
case 'm':
max_sec = atoi(optarg);
break;
case 't':
hept_vcd_init(optarg, VCD_TIME_UNIT_US, 20);
break;
default:
fprintf(stderr, "Unknown option '%c'\n", opt);
exit(EXIT_FAILURE);
}
}
if (SDL_Init(SDL_INIT_AUDIO) < 0)
die("Could not initialize SDL2\n");
/* Specification of requested output device. */
bzero(&spec, sizeof spec);
spec.freq = sample_rate; /* Samples per second */
spec.format = AUDIO_F32; /* Sample format: IEEE-754 32 bits */
spec.channels = 2; /* Two channels */
spec.samples = 4096; /* Buffers sized 4 KiB */
spec.callback = NULL;
if (!(dev = SDL_OpenAudioDevice(NULL, 0, &spec, NULL, 0)))
die("Could not open audio device\n");
if (filename != NULL) {
/* Specification of requested output file, if any. */
SF_INFO info_out;
bzero(&info_out, sizeof info_out);
info_out.channels = 2; /* Two channels */
info_out.samplerate = sample_rate; /* Samples per second */
info_out.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16; /* File format */
if (!(file_out = sf_open(filename, SFM_WRITE, &info_out))) {
fprintf(stderr, "Could not open WAV file %s for writing\n", argv[1]);
SDL_Quit();
exit(EXIT_FAILURE);
}
}
Audio__main_reset(&mem);
float *buffer = calloc(spec.samples, sizeof *buffer);
SDL_PauseAudioDevice(dev, 0);
/* Loop until we've produced the requested amount of samples, that is the
duration in seconds multiplied by the number of samples per second. This
number of samples shall be sent on each of both stereo channels.
Each iteration sends spec.samples stereo samples to the audio device,
hence we halve it to get the number of generated samples per-channel. */
for (size_t samples = 0;
samples < max_sec * sample_rate;
samples += spec.samples / 2) {
/* Print sound progress. */
printf("\rSent %08zu samples", samples);
if (max_sec != SIZE_MAX) {
printf(" (%2.0f%)", 100. * (double)samples / (max_sec * sample_rate));
}
fflush(stdout);
/* Exit immediately if requested, e.g., the user pressed Ctrl-C. */
if (SDL_QuitRequested()) {
printf("\n");
return 1;
}
/* Step the node as much as necessary to fill a buffer. Each step produces
one stereo sample. */
for (size_t i = 0; i < spec.samples; i += 2) {
Audio__main_step(&res, &mem);
buffer[i+0] = res.o.l;
buffer[i+1] = res.o.r;
}
/* Send the generated sound to the sound card and/or file. */
if (!quiet)
SDL_QueueAudio(dev, buffer, spec.samples * sizeof *buffer);
if (file_out)
sf_writef_float(file_out, buffer, spec.samples / 2);
/* Throttle queued audio, otherwise we will certainly end up consuming all
available memory. */
buffered = SDL_GetQueuedAudioSize(dev);
while (!quiet && buffered >= 1 << 22) {
SDL_Delay(50);
buffered = SDL_GetQueuedAudioSize(dev);
}
}
printf("\n");
/* Wait until the audio buffer is empty. */
printf("Waiting for queue flush... "); fflush(stdout);
while ((buffered = SDL_GetQueuedAudioSize(dev)) != 0)
SDL_Delay(50);
printf("done.\n");
free(buffer);
if (file_out)
sf_close(file_out);
SDL_Quit();
return 0;
}

55
cours/audio/mathext.c Normal file
View File

@@ -0,0 +1,55 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Avoid Heptagon's math.h. I don't think there's a single place where to find
math.h on Apple-platforms. */
#ifndef __APPLE__
#include </usr/include/math.h>
#endif
#include "mathext.h"
void Mathext__float_step(int x, Mathext__float_out *o) {
o->o = (float)x;
}
void Mathext__int_step(float x, Mathext__int_out *o) {
o->o = (int)x;
}
void Mathext__floor_step(float x, Mathext__floor_out *o) {
o->o = floorf(x);
}
void Mathext__sin_step(float x, Mathext__sin_out *o) {
o->o = sinf(x);
}
void Mathext__cos_step(float x, Mathext__cos_out *o) {
o->o = cosf(x);
}
void Mathext__atan2_step(float y, float x, Mathext__atan2_out *o) {
o->o = atan2f(y, x);
}
void Mathext__pow_step(float x, float y, Mathext__pow_out *o) {
o->o = powf(x, y);
}
void Mathext__hypot_step(float x, float y, Mathext__hypot_out *o) {
o->o = hypotf(x, y);
}
void Mathext__sqrt_step(float x2, Mathext__sqrt_out *o) {
o->o = sqrtf(x2);
}
void Mathext__modulo_step(int x, int y, Mathext__modulo_out *o) {
o->o = x % y;
}
void Mathext__piano_freq_of_key_step(int n, Mathext__piano_freq_of_key_out *o) {
o->f = (float)(pow(2, (float)(n - 49) / (float)12) * 440.);
}

16
cours/audio/mathext.epi Normal file
View File

@@ -0,0 +1,16 @@
external fun float(x : int) returns (o : float)
external fun int(x : float) returns (o : int)
external fun floor(x : float) returns (o : float)
external fun sin(x : float) returns (o : float)
external fun cos(x : float) returns (o : float)
external fun atan2(y : float; x : float) returns (o : float)
external fun hypot(x : float; y : float) returns (o : float)
external fun sqrt(x2 : float) returns (o : float)
external fun pow(x : float; y : float) returns (o : float)
external fun modulo(x : int; y : int) returns (o : int)
external fun piano_freq_of_key(k : int) returns (f : float)
const pi : float = 3.14115

27
cours/audio/mathext.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef MATHEXT_H
#define MATHEXT_H
#include "stdbool.h"
#include "assert.h"
#include "pervasives.h"
#include "hept_ffi.h"
DECLARE_HEPT_FUN(Mathext, float, (int), float o);
DECLARE_HEPT_FUN(Mathext, int, (float), int o);
DECLARE_HEPT_FUN(Mathext, floor, (float), float o);
DECLARE_HEPT_FUN(Mathext, sin, (float), float o);
DECLARE_HEPT_FUN(Mathext, cos, (float), float o);
DECLARE_HEPT_FUN(Mathext, atan2, (float, float), float o);
DECLARE_HEPT_FUN(Mathext, hypot, (float, float), float o);
DECLARE_HEPT_FUN(Mathext, sqrt, (float), float o);
DECLARE_HEPT_FUN(Mathext, pow, (float, float), float o);
DECLARE_HEPT_FUN(Mathext, modulo, (int, int), int o);
DECLARE_HEPT_FUN(Mathext, piano_freq_of_key, (int), float f);
static const float Mathext__pi = 3.14115;
#endif /* MATHEXT_H */

View File

@@ -0,0 +1,4 @@
#ifndef MATHEXT_TYPES_H
#define MATHEXT_TYPES_H
#endif /* MATHEXT_TYPES_H */

75
cours/audio/vcd.c Normal file
View File

@@ -0,0 +1,75 @@
#include "vcd.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "vcd_lib.h"
vcd_file_t *vcd = NULL;
bool enabled = false;
void hept_vcd_cleanup() {
if (vcd) {
printf("[vcd] saving trace\n");
vcd_file_write(vcd);
vcd_file_free(vcd);
}
}
void hept_vcd_init(const char *filename,
size_t time_number,
vcd_time_unit_t unit) {
if (vcd) {
fprintf(stderr, "[vcd] initialization has already been performed\n");
} else {
vcd = vcd_file_alloc(filename, time_number, unit);
assert (vcd);
if (atexit(hept_vcd_cleanup)) {
perror("[vcd] atexit() failed");
exit(EXIT_FAILURE);
}
printf("[vcd] will save trace to %s\n", filename);
}
}
static inline void trace_samples(vcd_signal_t **signal,
const char *name, vcd_signal_type_t type,
void *samples, size_t count) {
if (!vcd)
return;
if (!*signal) {
*signal = vcd_signal_alloc(name, type, 1 << 17);
if (!vcd_file_add_signal(vcd, *signal)) {
perror("vcd_file_add_signal()\n");
exit(EXIT_FAILURE);
}
}
vcd_add_samples(*signal, samples, count);
}
DEFINE_HEPT_NODE_RESET(Vcd, trace_bool) {
mem->signal = NULL;
}
DEFINE_HEPT_NODE_STEP(Vcd, trace_bool, (string name, int v)) {
trace_samples(&mem->signal, name, VCD_SIGNAL_TYPE_BOOL, &v, 1);
}
DEFINE_HEPT_NODE_RESET(Vcd, trace_int) {
mem->signal = NULL;
}
DEFINE_HEPT_NODE_STEP(Vcd, trace_int, (string name, int v)) {
trace_samples(&mem->signal, name, VCD_SIGNAL_TYPE_INT, &v, 1);
}
DEFINE_HEPT_NODE_RESET(Vcd, trace_float) {
mem->signal = NULL;
}
DEFINE_HEPT_NODE_STEP(Vcd, trace_float, (string name, float v)) {
trace_samples(&mem->signal, name, VCD_SIGNAL_TYPE_FLOAT, &v, 1);
}

6
cours/audio/vcd.epi Normal file
View File

@@ -0,0 +1,6 @@
(* A basic library for producing VCD files from Heptagon code, typically used
for debugging purposes. *)
external node trace_bool(name : string; v : bool) returns ()
external node trace_int(name : string; v : int) returns ()
external node trace_float(name : string; v : float) returns ()

18
cours/audio/vcd.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef VCD
#define VCD
#include <stdbool.h>
#include <stddef.h>
#include "hept_ffi.h"
#include "vcd_lib.h"
void hept_vcd_init(const char *filename,
size_t time_number,
vcd_time_unit_t unit);
DECLARE_HEPT_NODE(Vcd, trace_bool, (string, int),, vcd_signal_t *signal);
DECLARE_HEPT_NODE(Vcd, trace_int, (string, int),, vcd_signal_t *signal);
DECLARE_HEPT_NODE(Vcd, trace_float, (string, float),, vcd_signal_t *signal);
#endif /* VCD */

198
cours/audio/vcd_lib.c Normal file
View File

@@ -0,0 +1,198 @@
#include "vcd_lib.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "buffer.h"
size_t vcd_sizeof_signal_type(vcd_signal_type_t type) {
switch (type) {
case VCD_SIGNAL_TYPE_BOOL:
return sizeof(int);
case VCD_SIGNAL_TYPE_INT:
return sizeof(int);
case VCD_SIGNAL_TYPE_FLOAT:
return sizeof(float);
}
}
typedef struct vcd_signal {
char *name;
vcd_signal_type_t type;
buffer_t *samples;
} vcd_signal_t;
vcd_signal_t *vcd_signal_alloc(const char *name,
vcd_signal_type_t type,
size_t initial_buffer_size) {
vcd_signal_t *res = malloc_checked(sizeof *res);
res->name = strdup_checked(name);
res->type = type;
res->samples =
buffer_alloc(initial_buffer_size * vcd_sizeof_signal_type(type));
return res;
}
void vcd_signal_free(vcd_signal_t *signal) {
assert (signal);
buffer_free(signal->samples);
free(signal->name);
free(signal);
}
void vcd_add_samples(vcd_signal_t *signal, void *samples, size_t count) {
assert (signal);
assert (samples);
buffer_write(signal->samples,
samples,
count * vcd_sizeof_signal_type(signal->type));
}
const char *vcd_time_unit_repr(vcd_time_unit_t u) {
const char *table[] = { "s", "ms", "us", "ns", "ps", "fs" };
assert (VCD_TIME_UNIT_S <= u && u <= VCD_TIME_UNIT_FS);
return table[u];
}
typedef struct vcd_file {
char *filename;
buffer_t *signals;
vcd_time_unit_t time_unit;
size_t time_unit_factor;
} vcd_file_t;
vcd_file_t *vcd_file_alloc(const char *filename,
vcd_time_unit_t time_unit,
size_t time_unit_factor) {
assert (filename);
vcd_file_t *vcd = malloc_checked(sizeof *vcd);
vcd->filename = strdup_checked(filename);
vcd->time_unit = time_unit;
vcd->time_unit_factor = time_unit_factor;
vcd->signals = buffer_alloc(10 * sizeof(vcd_signal_t));
return vcd;
}
void vcd_file_free(vcd_file_t *vcd) {
assert (vcd);
/* Free buffers. */
buffer_foreach (vcd_signal_t *, psig, vcd->signals)
vcd_signal_free(*psig);
buffer_free(vcd->signals);
free(vcd->filename);
free(vcd);
}
vcd_signal_t *vcd_file_lookup_signal(const vcd_file_t *vcd, const char *name) {
assert (vcd);
assert (name);
vcd_signal_t *res = NULL;
buffer_foreach (vcd_signal_t *, psig, vcd->signals) {
if (strcmp((*psig)->name, name) == 0) {
res = *psig;
break;
}
}
return res;
}
bool vcd_file_add_signal(const vcd_file_t *vcd, vcd_signal_t *signal) {
assert (vcd);
assert (signal);
if (vcd_file_lookup_signal(vcd, signal->name))
return false;
buffer_write(vcd->signals, &signal, sizeof signal);
return true;
}
bool vcd_file_write(vcd_file_t *vcd) {
FILE *f = fopen(vcd->filename, "w");
if (!f)
return false;
time_t current_time;
time(&current_time);
fprintf(f, "$version Generated by vcd.c $end\n");
fprintf(f, "$date %s $end\n", ctime(&current_time));
fprintf(f, "$timescale %zu %s $end\n",
vcd->time_unit_factor,
vcd_time_unit_repr(vcd->time_unit));
/* Dump signal declarations. */
fprintf(f, "$scope module Top $end\n");
buffer_foreach (vcd_signal_t *, psig, vcd->signals) {
fprintf(f, "$var ");
switch ((*psig)->type) {
case VCD_SIGNAL_TYPE_BOOL:
fprintf(f, "wire 1");
break;
case VCD_SIGNAL_TYPE_INT:
fprintf(f, "integer %zu", 8 * sizeof(int));
break;
case VCD_SIGNAL_TYPE_FLOAT:
fprintf(f, "real 32");
break;
}
fprintf(f, " %p %s $end\n", (*psig), (*psig)->name);
}
fprintf(f, "$upscope $end\n");
fprintf(f, "$enddefinitions\n");
/* Dump samples. */
fprintf(f, "$dumpvars\n");
/* We maintain a pointer to the current sample in each buffer. */
size_t signal_count = vcd->signals->occupancy / sizeof(vcd_signal_t *);
unsigned char **psamples = calloc(signal_count, sizeof(unsigned char *));
assert (psamples);
for (size_t i = 0; i < signal_count; i++)
psamples[i] = ((vcd_signal_t **)vcd->signals->data)[i]->samples->data;
/* We dump */
bool active = true;
for (size_t step = 0; active; step++) {
fprintf(f, "#%zu\n", step);
active = false;
for (size_t i = 0; i < signal_count; i++) {
vcd_signal_t *sig = ((vcd_signal_t **)vcd->signals->data)[i];
if (psamples[i] < sig->samples->data + sig->samples->occupancy) {
active = true;
switch (sig->type) {
case VCD_SIGNAL_TYPE_BOOL:
fprintf(f, "%d%p\n", (*(int *)psamples[i] ? 1 : 0), sig);
psamples[i] += sizeof(int);
break;
case VCD_SIGNAL_TYPE_INT:
fprintf(f, "r%d %p\n", *(int *)psamples, sig);
psamples[i] += sizeof(int);
break;
case VCD_SIGNAL_TYPE_FLOAT:
fprintf(f, "r%.16g %p\n", *(float *)psamples, sig);
psamples[i] += sizeof(float);
break;
}
}
}
}
free(psamples);
fclose(f);
return true;
}

47
cours/audio/vcd_lib.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef VCD_LIB_H
#define VCD_LIB_H
#include <stdbool.h>
#include <stddef.h>
typedef enum vcd_signal_type {
VCD_SIGNAL_TYPE_FLOAT,
VCD_SIGNAL_TYPE_INT,
VCD_SIGNAL_TYPE_BOOL
} vcd_signal_type_t;
size_t vcd_sizeof_signal_type(vcd_signal_type_t);
typedef struct vcd_signal vcd_signal_t;
vcd_signal_t *vcd_signal_alloc(const char *name,
vcd_signal_type_t type,
size_t initial_buffer_size);
void vcd_signal_free(vcd_signal_t *signal);
void vcd_add_samples(vcd_signal_t *signal, void *samples, size_t count);
typedef enum vcd_time_unit {
VCD_TIME_UNIT_S,
VCD_TIME_UNIT_MS,
VCD_TIME_UNIT_US,
VCD_TIME_UNIT_NS,
VCD_TIME_UNIT_PS,
VCD_TIME_UNIT_FS,
} vcd_time_unit_t;
const char *vcd_time_unit_repr(vcd_time_unit_t);
typedef struct vcd_file vcd_file_t;
vcd_file_t *vcd_file_alloc(const char *filename,
vcd_time_unit_t time_unit,
size_t time_unit_factor);
void vcd_file_free(vcd_file_t *);
vcd_signal_t *vcd_file_lookup_signal(const vcd_file_t *vcd, const char *name);
bool vcd_file_add_signal(const vcd_file_t *vcd, vcd_signal_t *signal);
bool vcd_file_write(vcd_file_t *);
#endif /* VCD_LIB_H */

4
cours/audio/vcd_types.h Normal file
View File

@@ -0,0 +1,4 @@
#ifndef VCD_TYPES
#define VCD_TYPES
#endif /* VCD_TYPES */

View File

@@ -0,0 +1,62 @@
HEPTC=heptc
PYGMENTS=python -m pygments -x -l ../../../notes/heptagon.py:HeptagonLexer
HEPT_NAME=pendulum
HEPT_SOURCES=$(HEPT_NAME).ept
HEPT_GENERATED=\
$(HEPT_NAME)_types.h \
$(HEPT_NAME).h \
$(HEPT_NAME)_types.c \
$(HEPT_NAME).c
C_SOURCES=mathext.c
SWIG_SOURCE=$(HEPT_NAME).i
SWIG_GENERATED=$(HEPT_NAME).py $(HEPT_NAME)_wrap.c
PY_SUFFIX=$(shell python -c \
"import sysconfig as s; print(s.get_config_var('EXT_SUFFIX'))")
TARGET?=_$(HEPT_NAME)$(PY_SUFFIX)
HTML=pendulum.html
.PHONY: all clean run runplot repl
all: $(TARGET)
clean:
rm -f *.epci *.log *.mls *.obc *.epci *.epo
rm -f $(SWIG_GENERATED) $(HEPT_GENERATED)
rm -rf $(HEPT_NAME)_c build __pycache__ *.so
rm -f $(HTML)
repl: all
python -i -c 'import $(HEPT_NAME)'
run: all
./main.py
runplot: all
./main.py --plot
%.html: %.ept
$(PYGMENTS) -O full -o $@ $^
$(TARGET): $(SWIG_GENERATED) $(HEPT_GENERATED) $(C_SOURCES)
python setup.py build_ext --inplace
@echo $@
$(SWIG_GENERATED): $(SWIG_SOURCE) $(HEPT_GENERATED) $(C_SOURCES)
swig -python $<
%_types.h %_types.c %.c %.h %.epci : %.ept
$(HEPTC) -c -target c $<
cp $(foreach ext,c h,$(basename $<)_c/*.$(ext)) .
%.epci: %.epi
$(HEPTC) $<
$(HEPT_SOURCES): mathext.epci debug.epci
%.html: %.ept
$(PYGMENTS) -O full -o $@ $^

View File

@@ -0,0 +1,43 @@
# Pendule inversé et contrôleur PID
## Présentation
Ce dossier contient un exemple classique de système physique qu'on peut chercher
à contrôler, le pendule inversé.
## Dépendances
Le projet utilise du code Python 3, et le générateur d'interfaces SWIG pour
exposer le code C généré par Heptagon à Python. Pour le lancer, vous devez :
- avoir Heptagon, à installer via OPAM,
- avoir SWIG, à installer via le gestionnaire de paquet de votre système
d'exploitation (`apt-get` sous GNU/Linux Debian ou Ubuntu, `pacman` sous Arch
Linux, `brew` sous macOS, etc.),
- avoir la bibliothèque Python `matplotlib`, à installer `pip install --user
matplotlib`.
## Utilisation
Vous pouvez lancer le programme en exécutant `make run`.
Pour lancer le programme avec l'affichage des courbes, exécutez `make runplot`.
Attention : afficher les courbes engendre un ralentissement assez conséquent.
L'interface utilisateur fonctione de la façon suivante :
- **Q** permet de quitter,
- **P** permet de mettre en pause,
- **R** permet de réinitialiser la simulation,
- **M** permet de changer de mode (manuel, contrôleur PID, contrôleur BangBang),
- **←** et **→** permettent de déplacer le mobile,
- **clic gauche** permet de déplacer le mobile à la souris.
Les deux dernières commandes ne fonctionnent qu'en mode manuel.

View File

@@ -0,0 +1,88 @@
/* This file is part of SyncContest.
Copyright (C) 2017-2020 Eugene Asarin, Mihaela Sighireanu, Adrien Guatto. */
#include "cutils.h"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
log_verbosity_level level = LOG_INFO;
FILE *f = NULL;
char *filename = NULL;
void log_set_verbosity_level(log_verbosity_level l) {
level = l;
}
void log_message_v(log_verbosity_level msg_level, const char *fmt, va_list va) {
va_list vb;
FILE *out = msg_level == LOG_INFO ? stdout : stderr;
if (msg_level > level)
return;
va_copy(vb, va);
if (f != NULL) {
vfprintf(f, fmt, va);
}
vfprintf(out, fmt, vb);
fflush(out);
}
void log_message(log_verbosity_level msg_level, const char *fmt, ...) {
va_list va;
va_start(va, fmt);
log_message_v(msg_level, fmt, va);
va_end(va);
}
void log_fatal(const char *fmt, ...) {
va_list va;
va_start(va, fmt);
log_message_v(LOG_FATAL, fmt, va);
va_end(va);
exit(EXIT_FAILURE);
}
void log_info(const char *fmt, ...) {
va_list va;
va_start(va, fmt);
log_message_v(LOG_INFO, fmt, va);
va_end(va);
}
void log_debug(const char *fmt, ...) {
va_list va;
va_start(va, fmt);
log_message_v(LOG_DEBUG, fmt, va);
va_end(va);
}
void log_init(const char *fn) {
if (!fn) {
log_info("[log] initializing, not saving to file\n");
return;
}
filename = strdup(fn);
assert (filename);
f = fopen(filename, "w");
if (!f)
log_fatal("[log] could not open log file %s (fopen)", filename);
log_info("[log] logging to %s\n", filename);
}
void log_shutdown() {
if (f) {
log_info("[log] shutting down, closing %s\n", filename);
fclose(f);
free(filename);
} else {
log_info("[log] shutting down\n");
}
}

View File

@@ -0,0 +1,30 @@
/* This file is part of SyncContest.
Copyright (C) 2017-2020 Eugene Asarin, Mihaela Sighireanu, Adrien Guatto. */
#ifndef CUTILS_H
#define CUTILS_H
#include <stdarg.h>
typedef enum {
LOG_FATAL = 0,
LOG_INFO = 1,
LOG_DEBUG = 2,
} log_verbosity_level;
/* Calling `log_init(fn)` initializes the logging subsystem, asking it to save
log messages to the file `fn`. This pointer may be NULL, in which case the
messages are not saved. */
void log_init(const char *filename);
void log_shutdown();
void log_set_verbosity_level(log_verbosity_level level);
void log_message_v(log_verbosity_level level, const char *fmt, va_list);
void log_message(log_verbosity_level level, const char *fmt, ...);
void log_fatal(const char *fmt, ...);
void log_info(const char *fmt, ...);
void log_debug(const char *fmt, ...);
#endif /* CUTILS_H */

View File

@@ -0,0 +1,39 @@
#include "debug.h"
#include "cutils.h"
void Debug__dbg_step(char *msg, Debug__dbg_out *o) {
log_info("%s\n", msg);
}
void Debug__dbg_bool_step(char *msg, bool x, Debug__dbg_bool_out *o) {
log_info("%s %d\n", msg, x);
}
void Debug__dbg_int_step(char *msg, int x, Debug__dbg_int_out *o) {
log_info("%s %d\n", msg, x);
}
void Debug__dbg_float_step(char *msg, float x, Debug__dbg_float_out *o) {
log_info("%s %f\n", msg, x);
}
void Debug__d_init_step(Debug__d_init_out *o) {
/* Empty by design */
}
void Debug__d_string_step(Debug__world _w, char *s, Debug__d_string_out *o) {
log_info("%s", s);
}
void Debug__d_bool_step(Debug__world _w, bool b, Debug__d_bool_out *o) {
log_info("%d", b);
}
void Debug__d_int_step(Debug__world _w, int i, Debug__d_int_out *o) {
log_info("%d", i);
}
void Debug__d_float_step(Debug__world _w, float f, Debug__d_float_out *o) {
log_info("%f", f);
}

View File

@@ -0,0 +1,11 @@
external fun dbg(msg : string) returns ()
external fun dbg_bool(msg : string; x : bool) returns ()
external fun dbg_int(msg : string; x : int) returns ()
external fun dbg_float(msg : string; x : float) returns ()
type world
external fun d_init() returns (n : world)
external fun d_string(w : world; string) returns (n : world)
external fun d_bool(w : world; bool) returns (n : world)
external fun d_int(w : world; int) returns (n : world)
external fun d_float(w : world; float) returns (n : world)

View File

@@ -0,0 +1,23 @@
#ifndef DEBUG_H
#define DEBUG_H
#include "stdbool.h"
#include "assert.h"
#include "pervasives.h"
#include "hept_ffi.h"
DECLARE_HEPT_FUN(Debug, dbg, (char *),);
DECLARE_HEPT_FUN(Debug, dbg_bool, (char *, bool),);
DECLARE_HEPT_FUN(Debug, dbg_int, (char *, int),);
DECLARE_HEPT_FUN(Debug, dbg_float, (char *, float),);
typedef struct { } Debug__world;
DECLARE_HEPT_FUN_NULLARY(Debug, d_init, Debug__world n);
DECLARE_HEPT_FUN(Debug, d_string, (Debug__world, char *), Debug__world n);
DECLARE_HEPT_FUN(Debug, d_bool, (Debug__world, bool), Debug__world n);
DECLARE_HEPT_FUN(Debug, d_int, (Debug__world, int), Debug__world n);
DECLARE_HEPT_FUN(Debug, d_float, (Debug__world, float), Debug__world n);
#endif /* DEBUG_H */

View File

@@ -0,0 +1,4 @@
#ifndef DEBUG_TYPES_H
#define DEBUG_TYPES_H
#endif /* DEBUG_TYPES_H */

Some files were not shown because too many files have changed in this diff Show More