Skip to content

Commit

Permalink
Merge branch 'master' of git@github.com:Rip-Rip/ihy
Browse files Browse the repository at this point in the history
  • Loading branch information
Teddy Wagnac committed May 27, 2009
2 parents 3ba7a42 + 8f0b0b2 commit 3dab7c7
Show file tree
Hide file tree
Showing 6 changed files with 303 additions and 20 deletions.
119 changes: 115 additions & 4 deletions doc/reports/soutenance3/soutenance3.tex
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ \section*{Introduction générale}
intégrale du cahier des charges, pour mettre en relief ce que nous voulions
faire et ce que nous avons finalement réalisé. En deuxième partie nous verrons
la chronologie du projet tel que nous l'avons fait. Enfin la dernière partie
A REMPLIR.\\
exprimera nos regrets sur ce projet.

\tableofcontents

Expand Down Expand Up @@ -136,8 +136,11 @@ \subsection{Le petit imprévu}
Toujours est-il que cela fonctionne, et donc n'importe qui peut désormais
écouter un fichier ihy, ou qu'il se trouve, sur un iPhone.
\subsection{Conclusion partielle}
A REMPLIR !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Cette deuxieme soutenance a ete un grand pas dans l'avancement de
notre projet. Nous avions enfin un codec utlile qui compressait
reellement tout en gardant une bonne qualitee. Quel bonheur de pouvoir
ecouter sa musique encode avec son propre codec sur son ordinateur, ou
encore mieu, sur son balladeur.
\newpage

\section{Troisième soutenance}
Expand Down Expand Up @@ -212,6 +215,114 @@ \subsection{Débits binaire}
Il ne nous restait plus qu'à définir un certains nombre de débits en fonction de
la qualité audio recherchée. Quatre qualités sont disponible, auxquelles sont
associées quatre débits binaire, du plus faible au plus important : 128 kbits/s,
192 kbits/s, 256 kbits/s et 320 kbits/s.
192 kbits/s, 256 kbits/s et 320 kbits/s.\\
Ainsi, les chunks contenant peu d'informations seront codés avec un maximum de
bits, assurant la beauté du signal, alors que les chunks ayant beaucoup
d'informations seront au contraire sur-compressés impliquant un signal de plus
en plus détruit, l'oreille a tendance à fait abstraction des défauts.
\subsection{Ondelettes}
A la soutenance precdente, nous avions implemente la compression par
une nouvelle famille d'ondelettes, Daubechies. Depuis, nous avons
egalement fait la decompression, chose qui n'a pas ete facile.\\
La, nous esperions de biens meilleurs resultats, mais nous
avons finalement ete decu. En effet, malgres de nombreux tests sur les
traitements des coefficients nous n'avons pas reussi a avoir de
meilleurs resultats qu'avec l'ondelette de Haar. Nous sommes donc
revenu en arriere et avons garde la premiere.
\subsection{Psychoacoustique}
Nous avons implementer deux nouvelles techniques de psychoacoustique
qui nous a permis de supprimer une partie des coefficients sans que ce
soit audible a l'oreille humaine.
\subsubsection{Hautes frequences}
Depuis la soutenance precedante nous enlevons deja les coefficients
correspondants au hautes frequences. La nous avons affine le
traitement en supprimant plus de coefficients correspondants aux
petits variations aux hautes frequences. Nous avons donc deja pu
gagner un peu de place.
\subsubsection{Masquage}
Lorsque a un meme moment nous avons a la fois un signal a basse
frequence assez fort et un deuxieme a haute frequence, celui-ci est
masque par le premier. Nous avons donc cherche a comprendre quels
coefficients correspondaient a quels frequences. La nous avons reussi
a supprimer certains coefficients qui n'influent pas sur la qualite du
son mais le gain de place est malheuresement negligeable avec cette technique.
\subsection{Interface graphique}
\subsection{Comparaison inter-codecs}
La section précédente implique directement celle-ci. Mais que vaut réellement
notre codec? Est-il performant? Est-il à la hauteur? Remplacera-t'il le mp3 dans
nos lecteurs portables?\\
Nous pourrions vous montrer des graphiques, des analyses du spectre audio et
autres fioritures pour vous prouver que notre codec est à la hauteur. Mais ce
que cela ne montrerai pas c'est la qualité auditive. Pour cela rien de vaut une
écoute à l'aveugle, et sur ce point, il faut le dire\footnote{Attention à la
déception}, le son est inaudible a 128 kbits/s. Le son original est certes
toujours présent mais perdu au milieu d'un souffle ambiant. Pour faire une
comparaison avec ce qui a existé, il suffit de reprendre un vieux vinyle qui a
pris la poussière pendant une dizaine d'année (voir plus) et de l'écouter, il
suffit d'imaginer le son que cela risque de produire pour grincer des dents et
avoir peur pour ses oreilles.\\
Par contre, a des débits plus élevés, c'est à dire 256 kbits/s et 320 kbits/s,
le son est parfaitement audible et peut même être comparé avec le son original.
Les seuls différences se situent au niveau des moments ``intense'', ou le
souffle commence un peu à se faire sentir (il faut néanmoins tendre l'oreille ou
être habitué).\\
Il est de notoriété publique que les tests de codecs se font dans des débits
faibles, et que passer 256kbits/s, tous se ressemble et peu de gens sont capable
de dire quel codec est meilleur. Le notre en fait heureusement parti.
\chapter{Regrets}
Il s'agit bien évidement du fait que notre codec n'est pas en mesure de
concurrencer les codecs usuellement utilisés tels que le mp3, vorbis, wma, \ldots.
De plus, quelques algorithmes aurait pu être utilisés autrement, et d'autre
utilisés.\\
\section{Algorithme de Huffman}
Commençons par l'algorithme de Huffman. Dans son implantation actuelle, on doit,
pour chaque chunk reconstruire un nouvel arbre et le réécrire intégralement.
Bien sûr cela a l'avantage de produire des arbres localement parfait (dans le
sens ou il encore de façon optimale), mais cela a l'inconvénient d'avoir à
écrire l'arbre. Un arbre prend de façon exacte 771 octets, dans notre
implémentation actuelle, soit 771 octets pour trois-quarts de seconde dans le
cas d'un signal double canaux. Soit, en chiffrant, 8 kbits/s de base, sans avoir
aucun signal, ce qui est dans les débits que l'on utilise, peu, mais dans le cas
d'un véritable codec, ie qui peut encoder a 64 kbits/s, beaucoup.\\
La solution aurai été d'avoir une base de donnée de plusieurs arbres de Huffman
et de choisir le meilleur pour chaque chunk.
\section{Quantification vectorielle}
La quantification vectorielle, autre technique de quantification est notamment
utilisée dans le codec vorbis, elle permet de quantifier des flottants de façon
plus juste qu'une simple quantification, permettant d'avoir le moins de perte
possible, tout en conservant une très bonne qualité après reconstitution. Il
s'agit plus ou moins d'une étude statistique des coefficients, avec évolution
intelligente, implanté à l'aide d'un réseau de neurones.\\
On peut considérer que cela aurai améliorer grandement la qualité sans impacter
la taille du fichier.
\section{Allocateur de bits}
Derrière ces termes un peu barbare se cache une chose très simple. Plutôt que de
faire comme on l'a fait, c'est à dire avec un bitrate constant sur tous les
chunks, il s'agit d'allouer un nombre de bit fixe qui servira pour tout le
fichier, que l'on peut calculer simplement en multipliant le débit que l'on
souhaite par la durée de la musique.\\
Il s'agit ensuite de correctement distribuer l'espace disponible aux chunks les
plus nécessiteux, c'est-à-dire aux chunks dont la compression déforme le plus le
signal. Si le procédé est correctement réalisé, on se retrouve avec un signal
qui ne peut être meilleur pour le bitrate demandé.
\section{Ondelettes}
Nous avons d'abord implemente l'ondelette de Haar, ce qui a ete
relativement simple ce qui nous a permis de rapidement atteindre de
bons resultats. Cependant nous en esperions de bien meilleurs avec
autre ondelette, celles de Daubechies. Nous avons ete surpris de
remarquer que au contraire, nous n'avions une perte de qualite. Donc,
malgres tout nos tests et le temps perdu a implementer cette
ondelette, nous sommes rester a Haar, que nous avions implementer des
le commencement du projet.
\chapter{Conclusion}
Pour résumer le projet, je dirai qu'il s'agissait d'un projet plus qu'ambitieux,
frôlant avec la recherche. En effet, on ne peut pas dire que les ondelettes
pullulent sur internet. On a essayé, on a presque réussi, il ne faut pas perdre
également de vue que nous ne sommes que 4 étudiants n'ayant aucune expérience
dans le domaine de la compression audio, codant sur une durée de 6mois.\\
Ce projet est donc une belle réussite si l'on considère les éléments
précédents, malgré le fait qu'il ne réalise pas nos espoirs, à savoir la
disparition du mp3 et de sa qualité plus que médiocre\footnote{l'hôpital qui se
fout de la charité}.

\end{document}
3 changes: 2 additions & 1 deletion src/cli/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ else
endif

CSRC=codecs/wav.c codecs/ihy.c audio_output/ao.c audio_output/wav_streaming.c \
audio_output/ihy_streaming.c compression/quantization.c \
audio_output/ihy_streaming.c audio_output/gui_streaming.c \
compression/quantization.c \
compression/wavelet.c compression/ihy.c compression/huffman.c \
utils/queue.c utils/buffer.c utils/half.c main_threading.c
COBJ=${CSRC:.c=.o}
Expand Down
142 changes: 142 additions & 0 deletions src/cli/audio_output/gui_streaming.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#include "gui_streaming.h"

/* General structure for played data */
struct gui_streaming_data
{
t_buffer buffer;
ihy_data *ihy;
int current_offset;
pthread_t playing_thread;
pthread_t filling_thread;
int status;
};

/* Structure and action made by the thread actually playing the sound */
struct s_playing_thread_data {
t_buffer buffer;
int *status;
ihy_data *ihy;
};
static void *playing_thread_action(void *data)
{
int continue_playing;
ao_device *playing_device;
int *to_play;
struct s_playing_thread_data *data2;

data2 = data;

continue_playing = 1;
playing_device = ao_init_device(16, data2->ihy->Channels, data2->ihy->Frequency);
to_play = NULL;

while (continue_playing)
{
if (*data2->status)
{
to_play = buffer_get(((t_playdata)data)->buffer);
if (to_play)
{
ao_play_samples(playing_device, to_play, data2->ihy->ChunkSize * 2);
free(to_play);
}
else
{
continue_playing = 0;
}
}
else
{
usleep(150000);
}
}

ao_close_device(playing_device);

return NULL;
}

/* Structure and action made by the thread filling the buffer */
struct s_filling_thread_data {
t_buffer buffer;
ihy_data *ihy;
int *status;
int *current_offset;
};
static void *filling_thread_action(void *data)
{
ihy_chunk *chunk;
int *to_add;
struct s_filling_thread_data *data2;

data2 = data;

while (*(data2->status))
{
chunk = &(data2->ihy->DataChunks[*data2->current_offset]);
to_add = calloc(data2->ihy->ChunkSize * 2, 1);
uncompress_chunk(chunk, (int8_t*)to_add, data2->ihy->Channels);
buffer_add(to_add, data2->buffer);
(*data2->current_offset)++;
}

return NULL;
}

/* Function creating a gui_straming_data based on some ihy data */
t_playdata create_gui_streaming(ihy_data *ihy)
{
t_playdata res;
struct s_filling_thread_data *ft_data;
struct s_playing_thread_data *pt_data;

res = malloc(sizeof(struct gui_streaming_data));
res->buffer = buffer_init(20);
res->ihy = ihy;
res->current_offset = 0;
ft_data = malloc(sizeof(struct s_filling_thread_data));
ft_data->buffer = res->buffer;
ft_data->status = &(res->status);
ft_data->current_offset = &(res->current_offset);
ft_data->ihy = ihy;
pt_data = malloc(sizeof(struct s_playing_thread_data));
pt_data->buffer = res->buffer;
pt_data->status = &(res->status);
pt_data->ihy = ihy;
pthread_create(&res->filling_thread, NULL, &filling_thread_action, ft_data);
pthread_create(&res->playing_thread, NULL, &playing_thread_action, pt_data);
res->status = 0;

return res;
}

/* Function controling the playback of the sound */
void play_gui_streaming(t_playdata played)
{
played->status = 1;
}

void pause_gui_streaming(t_playdata played)
{
played->status = 0;
}

void stop_gui_streaming(t_playdata played)
{
played = played;
}

void forward_gui_streaming(t_playdata played)
{
played = played;
}

void rewind_gui_streaming(t_playdata played)
{
played = played;
}

void destroy_gui_streaming(t_playdata played)
{
played = played;
}
20 changes: 20 additions & 0 deletions src/cli/audio_output/gui_streaming.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef DEF_GUI_STREAMING
#define DEF_GUI_STREAMING

#include <codecs/ihy.h>
#include <utils/buffer.h>
#include <audio_output/ao.h>
#include <compression/ihy.h>

typedef struct gui_streaming_data *t_playdata;

/* play the ihy in streaming */
t_playdata create_gui_streaming(ihy_data *ihy);
void play_gui_streaming(t_playdata played);
void pause_gui_streaming(t_playdata played);
void stop_gui_streaming(t_playdata played);
void forward_gui_streaming(t_playdata played);
void rewind_gui_streaming(t_playdata played);
void destroy_gui_streaming(t_playdata played);

#endif
12 changes: 6 additions & 6 deletions src/cli/compression/wavelets/haar.ml
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,16 @@ let mask (t : float_array) =

let compress (t : float_array) =
(* hf t;*)
mask t;
(* mask t; *)
(*removeFirsts t 2;*)
(*removeSeuil t 2 80.;*)
(* egalize t 2 30.; *)
(* removeSeuil t 2 30.; *)
t

let coef =
(2. ** (-.(1.)/.(2.)))
(* 1. /. 2.*)
(* (2. ** (-.(1.)/.(2.))) *)
1. /. 2.

let filter_direct x y =
coef *. (x +. y)
Expand All @@ -172,11 +172,11 @@ let filter_directD x y =
coef *. (y -. x)

let filter_reverse (y : float) (x : float) op=

(*
let coef' = coef *. 2. in
(op y x) /. coef'

(* (op y x) *)
*)
(op y x)


let haar_direct (a : float_array) =
Expand Down
Loading

0 comments on commit 3dab7c7

Please sign in to comment.