HectorDuino
Modérateurs : Papy.G, fneck, Carl
Re: HectorDuino
C'est pas faux, et effectivement j'ai un meilleur son sur la machine réelle.
Sur l'émulateur je suis à 44,1khz pour le son. j'avais utilisé une fréquence assez élevée pour être sur de ne pas avoir de soucis de ce type là (et je pensais être à l'abri de ça car pour moi le repliement était à 22khz et non à (44-X/2) khz et (44-X) khz...
A la limite, je pourrais peut être modifier l'ému pour passer un 88.2Khz ?
Bref, cela ne m'explique quand même pas pourquoi un son filtré ordre 1 est meilleur qu'ordre 2 je reste perplexe.
Sur l'émulateur je suis à 44,1khz pour le son. j'avais utilisé une fréquence assez élevée pour être sur de ne pas avoir de soucis de ce type là (et je pensais être à l'abri de ça car pour moi le repliement était à 22khz et non à (44-X/2) khz et (44-X) khz...
A la limite, je pourrais peut être modifier l'ému pour passer un 88.2Khz ?
Bref, cela ne m'explique quand même pas pourquoi un son filtré ordre 1 est meilleur qu'ordre 2 je reste perplexe.
Re: HectorDuino
J'ai donc travaillé un peu dessus et j'ai passé le fichier son joué en interne dans VBHector de 44,1KHz à 88.2 KHz et j'ai fini à 176,4KHz !
Cela ne ralenti en rien l'émulation, mais la synchro entre les cycles Z80 et la création d'un échantillon son se réduit comme peau de chagrin et donc l'erreur plus importante.
Par contre, et là c'est bien, le son devient comme par magie aussi bien que sur la machine réelle ! c'est bô les math !
Pour l'utilisation en player 1 bit c'est beaucoup mieux mais les sons 'classiques' (sn76477, 1bit dans les jeux etc...) deviennent plus problématique. Je pense mettre une option au démarrage 44,1KHz / 176,4KHz pour laisser le choix selon le test que l'on veut faire.
Cela ne ralenti en rien l'émulation, mais la synchro entre les cycles Z80 et la création d'un échantillon son se réduit comme peau de chagrin et donc l'erreur plus importante.
Par contre, et là c'est bien, le son devient comme par magie aussi bien que sur la machine réelle ! c'est bô les math !
Pour l'utilisation en player 1 bit c'est beaucoup mieux mais les sons 'classiques' (sn76477, 1bit dans les jeux etc...) deviennent plus problématique. Je pense mettre une option au démarrage 44,1KHz / 176,4KHz pour laisser le choix selon le test que l'on veut faire.
-
- Messages : 7967
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: HectorDuino
Ce que tu peux faire, c'est de toujours travailler à 44khz, mais tu n'envoie pas les échantillons tels quels vers l'audio. Tu les fait passer par un filtre passe-baseà 22khz.. comme ca les fréquences qui se replieront seront d'intensité rikiki, et le son sera de très bonne qualité.
Il doit y avoir plein de pointeurs pour pour programmer un FIR passe-bas 22khz avec un échantillonnage à 44khz. Par exemple avec: http://www.digitalfilter.com/products/d ... dfalz.html (bon il y a 90 coefs.. il faut scroller )
Il doit y avoir plein de pointeurs pour pour programmer un FIR passe-bas 22khz avec un échantillonnage à 44khz. Par exemple avec: http://www.digitalfilter.com/products/d ... dfalz.html (bon il y a 90 coefs.. il faut scroller )
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Re: HectorDuino
tu as raison sam, mais attention quand même, mon émulateur est écrit en VB Net et pas en C; c’était mon postulat de départ pour voir les capacités du VBNet... Actuellement lorsque je lance une émulation Hector + Arduino en video ou son je suis à près de 100% d'utilisation d'un thread de mon processeur. Ajouter trop de math est un problème.
Par contre j'ai trouvé un dernier index qui était en hard dans l'émulation son qui fait que maintenant même à 176,4KHz les sons sont correctes ! (sn76477, MEA8000 et 1 bit !!)
j'ai donc laissé à 176.4KHz pour tout le monde !
Remarque le filtre semble assez simple à réaliser...
Par contre j'ai trouvé un dernier index qui était en hard dans l'émulation son qui fait que maintenant même à 176,4KHz les sons sont correctes ! (sn76477, MEA8000 et 1 bit !!)
j'ai donc laissé à 176.4KHz pour tout le monde !
Remarque le filtre semble assez simple à réaliser...
-
- Messages : 7967
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: HectorDuino
un filtre FIR c'est pas trop de maths: c'est un buffer cyclique sur les N dernier échantillons audio, puis on fait une somme pondérée pour sortir la valeur. Grosso-modo un truc comme ca:
Après il y a des filtres meilleurs que d'autre. Les FIR font des osciilations dans la partie "plate" du spectre. Butterworth est mieux de ce point de vue.
J'ai pense, si ca se trouve l'api audio de windows fait déjà le boulot. Faudrait demander à Daniel comment est fait le filtre pour DCMoto. Codé en dur ou API simple à utiliser ?
Code : Tout sélectionner
.. globales
const N = taille
const coef[] = { .... };
var tab[N], index;
... code (local)
tab[index] = echantillon_non_filtré;
var v = 0
for i = 1 to N
v = v+ tab[(index+i) mod N]*coef[i]:
next
index = (index + 1) mod N
echantillon_filtré = v
sortir(echantillon_filtré)
J'ai pense, si ca se trouve l'api audio de windows fait déjà le boulot. Faudrait demander à Daniel comment est fait le filtre pour DCMoto. Codé en dur ou API simple à utiliser ?
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Re: HectorDuino
Dans dcmoto le signal est intégré pendant la période d'échantillonnage pour calculer l'échantillon à jouer, à la fréquence de 22050 échantillons par seconde. Il n'y a pas de filtre supplémentaire. C'est probablement le processus d'intégration qui limite les fréquences aigües. Avec un échantillonnage à 22050Hz on doit avoir une bande passante limitée à 11025Hz dans les aigus.
Daniel
L'obstacle augmente mon ardeur.
L'obstacle augmente mon ardeur.
-
- Messages : 7967
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: HectorDuino
Oui, un intégrateur est un filtre linéaire. C'est vrai que le filtrage est un plus quand on joue aux fréquences supérieures ou égales à la moitié de celle de restitution. Avec les 60khz du dither 1 bit on est vraiment dans ces conditions.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Re: HectorDuino
Salut à tous,
Juste un petit mot pour vous dire qu'une nouvelle version (3.0) de VBHetor est disponible sur le site d'Yves (merci Yves !).
Cette version intègre quelques nouveauté dont, notamment, l'intégration que mes utilitaires (création de fichiers Mini disque, création des vidéos et audios pour Hectorduino, création de wav à partir de fichier K7) ainsi que l'émulation complète de la platine HectorDuino permettant de jouer les sons et les vidéos visibles sur Hector+HectorDuino.
Pas mal de petites choses ont été reprises comme par exemple la synchro du son avec DirectX (beaucoup plus fine, maintenant un "TONE 300,100" en basic est comme sur la vrai machine, sans vibrato ou déformation), la scrutation du Z80 également reprise (sans impacts visible mais plus clair dans le programme), ...
J'ai également été plus clair dans les remerciements (dans l'à propos) pour être plus sûr des licences des softs utilisés (ffmepg, tniasm et la reprise du module modZ80 du projet VB81)
l'évolution majeure étant quand même la possibilité de visualiser les vidéo de l'HectorDuino !
Have fun !
JJ
PS : évidement il est possible que de bugs apparaissent, n'hésitez pas à me les décrire ici même !
[EDIT] avec un lien :
http://hectorvictor.free.fr/index.php?page=8BMh79AVpFsJ
Juste un petit mot pour vous dire qu'une nouvelle version (3.0) de VBHetor est disponible sur le site d'Yves (merci Yves !).
Cette version intègre quelques nouveauté dont, notamment, l'intégration que mes utilitaires (création de fichiers Mini disque, création des vidéos et audios pour Hectorduino, création de wav à partir de fichier K7) ainsi que l'émulation complète de la platine HectorDuino permettant de jouer les sons et les vidéos visibles sur Hector+HectorDuino.
Pas mal de petites choses ont été reprises comme par exemple la synchro du son avec DirectX (beaucoup plus fine, maintenant un "TONE 300,100" en basic est comme sur la vrai machine, sans vibrato ou déformation), la scrutation du Z80 également reprise (sans impacts visible mais plus clair dans le programme), ...
J'ai également été plus clair dans les remerciements (dans l'à propos) pour être plus sûr des licences des softs utilisés (ffmepg, tniasm et la reprise du module modZ80 du projet VB81)
l'évolution majeure étant quand même la possibilité de visualiser les vidéo de l'HectorDuino !
Have fun !
JJ
PS : évidement il est possible que de bugs apparaissent, n'hésitez pas à me les décrire ici même !
[EDIT] avec un lien :
http://hectorvictor.free.fr/index.php?page=8BMh79AVpFsJ
Re: HectorDuino
Sam, j'ai toujours eu un problème avec ton script que je ne comprend pas trop. Les notions de Perl m'étant toujours pas très familière.__sam__ a écrit : ↑06 oct. 2015 13:50Code : Tout sélectionner
#/bin/perl # Conversion video en gif 4 couls # # Samuel DEVULDER, Sept-Oct 2015. # # parametres ($W, $H) = (204, 153); # HR $fps = 10; $dither = "vac8"; ($RED,$GRN,$BLU) = (2,4,1); # fichier entree $file = $ARGV[0]; $out = $file; $out =~ s/\.[^\.]*$/.gif/; exit if -e $out; ($x,$y, $aspect_ratio) = (160,100,"16:9"); open(IN, "./ffmpeg -i \"$file\" 2>&1 |"); while(<IN>) { if(/, (\d+)x(\d+)/) { ($x,$y) = ($1, $2); # 4:3 if(abs($x - 4/3*$y) < abs($x - 16/9*$y)) { ($w,$h,$aspect_ratio) = (133,100,"4:3"); } } } close(IN); $h = int(($w=$W)*$y/$x); $w = int(($h=$H)*$x/$y) if $h>$H; print $file," : ${x}x${y} ($aspect_ratio) -> ${w}x${h}\n"; # dossier temporaire mkdir "tmp"; open(OUT,"| ./ffmpeg -i - -v 0 -r $fps -s ${w}x${h} -an tmp/img%05d.bmp"); open(IN, "<$file"); &init_magick; $gif = Image::Magick->new(size=>"${w}x${h}"); $cpt = 1; my @c = (0)x8; binmode(IN); binmode(OUT); while(1) { $name = sprintf("tmp/img%05d.bmp", $cpt); $expected_size = $h*(($w*3 + 3)&~3) + 54 if !$expected_size; if($expected_size != -s $name) { # image pas complete: on continue de nourrir ffmpeg my $buf; my $read = read(IN,$buf,4096); last unless $read; syswrite OUT, $buf, $read; } else { # image complete! print STDERR int($cpt++/$fps),"s\r"; sleep(5) if ($cpt%1200)==0; # on fait une pause régulière pour ne pas surchauffer le processeur # lecture de l'image my $img = Image::Magick->new(); $img->Read($name); unlink $name; # on force la saturation (140%) pour avoir des couleurs plus franches $img->Modulate(saturation=>140); $img->Evaluate(operator=>'Multiply', value=>255/245); my $tmp = Image::Magick->new(size=>"${W}x${H}"); $tmp->Read("xc:black"); $tmp->Composite(image=>$img, Operator=>"Over", x=>($W-$w)>>1, y=>($H-$h)>>1); undef $img; $img = $tmp; my $orig = $img->Clone(); # trammage $img->Set(colorspace=>$LINEAR_SPACE); $img->OrderedDither($dither); if(0) { # version R,G,B $img=$img->Fx(expression=>"(i+j)%3==0?r:0", channel=>"Red"); $img=$img->Fx(expression=>"(i+j)%3==1?g:0", channel=>"Green"); $img=$img->Fx(expression=>"(i+j)%3==2?b:0", channel=>"Blue"); } else { # détermination des 4 couleurs les plus fréquentes (histograme + passe-bas) my $z = $orig; if(!defined $gauss) { $gauss = Image::Magick->new(size=>"${W}x${H}"); $gauss->Read("xc:black"); $gauss=$gauss->Fx(expression=>"exp(-8*(((i-$W/2)/$W)^2 + ((j-$H/2)/$H)^2))", channel=>"All"); $gauss->Write("gauss.png"); } $z->Composite(image=>$gauss, Compose=>"Multiply", channel=>"All"); $z->Blur(sigma=>2); $z->Set(colorspace=>$LINEAR_SPACE); $z->OrderedDither($dither); $z->Write("gauss.png"); my @h = $z->Histogram(); my @H = (0)x8; for(my $i=$#h+1; ($i-=5)>=0;) { $H[($h[$i]&$RED)|($h[$i+1]&$GRN)|($h[$i+2]&$BLU)] = $h[$i+4]; } my @sf; for my $i (0..7) { my $t = int($c[$i] = ($c[$i]*0 + 32*$H[$i])/32); my $x = $t; $x |= $x>>1; $x |= $x>>2; $x |= $x>>4; $x |= $x>>8; $x |= $x>>16; ++$x; my $y = $x>>4; $x -= $y?$y:1; $t &= $x; $sf[$i]=$t*16 + ($i==0?8:$i); } @h = sort {$sf[$b]<=>$sf[$a]} (0..7); # print "\n"; # for my $i (@h) { # print $i, "=>", $sf[$i]>>4, " ",int($c[$i]), " (",$H[$i],")\n"; # } # construction d'une palette avec ces 4 couleurs my $k = join(',', @h[0..3]); my $m = $pal{$k}; if(!defined $m) { my(@px); for my $c (@h[0..3]) { push(@px, ($c&$RED)?255:0, ($c&$GRN)?255:0, ($c&$BLU)?255:0); } my $tmp = $ENV{'HOME'}."/.toto.pnm"; open(ZZ,">$tmp"); print ZZ "P6\n4 1\n255\n", pack('C*',@px),"\n"; close(ZZ); $m = Image::Magick->new(); $m->Read($tmp); unlink($tmp); $pal{$k} = $m; } # remping de l'image tramée sur ces 4 couleurs $img->Remap(image=>$m, 'dither-method'=>'none'); } $img->Write("toto.png"); # ajout de l'image au gif animé $img->Set(dispose=>"None"); $img->Set(delay=>int(100/$fps)); push(@$gif, $img); # pas plus de 3600 imgs (6mins) last if $cpt==4200; } } close(OUT); unlink(<$ENV{'HOME'}/img*.bmp>); # ecriture du fichier gif $gif->Set(dispose=>"None"); $gif->Set(Layers=>"optimize-trans"); $gif->Set(delay=>int(100/$fps)); $gif->Write($out); sub init_magick { # chargement image-magick la 1ere fois my($home) = "tmp"; $ENV{'HOME'} = $home; mkdir($home); mkdir("$home/.magick"); open(THR, ">$home/.magick/thresholds.xml"); print THR <<EOF; <thresholds> <threshold map="2x2"> <description>2x2 dither matrix</description> <levels width="2" height="2" divisor="5"> 1 2 3 4 </levels> </threshold> <threshold map="3x3"> <description>3x3 dither matrix</description> <levels width="3" height="3" divisor="10"> 7 8 2 6 9 4 3 5 1 </levels> </threshold> <threshold map="5x3"> <description>5x3 dither matrix</description> <levels width="3" height="5" divisor="16"> 3 9 4 8 14 10 13 15 11 7 12 5 2 6 1 </levels> </threshold> <threshold map="vac8"> <description>void and cluster 65 niveaux</description> <levels width="8" height="8" divisor="65"> 35 57 19 55 7 51 4 21 29 6 41 27 37 17 59 45 61 15 53 12 62 25 33 9 23 39 31 49 2 47 13 43 3 52 8 22 36 58 20 56 38 18 60 46 30 5 42 28 63 26 34 11 64 16 54 10 14 48 1 44 24 40 32 50 </levels> </threshold> </thresholds> EOF close(THR); eval 'use Image::Magick;'; # determination de l'espace RGB lineaire my $img = Image::Magick->new(size=>"256x1", depth=>16); $img->Read('gradient:black-white'); $img->Set(colorspace=>'RGB'); #$img->Set(colorspace=>"Gray") unless $coul; my @px1 = $img->GetPixel(x=>128, y=>0); $img->Read('gradient:black-white'); $img->Set(colorspace=>'sRGB'); #$img->Set(colorspace=>"Gray") unless $coul; my @px2 = $img->GetPixel(x=>128, y=>0); my $d1 = $px1[0]-0.5; $d1=-$d1 if $d1<0; my $d2 = $px2[0]-0.5; $d2=-$d2 if $d2<0; $LINEAR_SPACE = $d1>=$d2 ? "RGB" : "sRGB"; #print $px1[0], " ",$px2[0]," $LINEAR_SPACE\n"; }
Là où je bloque c'est dans le while(1) de la boucle de travail :
lorsque la vidéo dure moins longtemps que la limite dans le last (4200), les lignes après la fin du bloc du while ne sont pas exécutées et c'est pour ça que GIF ne se réalise pas.
Par contre je ne comprend pas comment on sort de ce while(1) en fin de traitement (lorsque toutes les images ont été traitées) et donc pourquoi on n'exécute pas la fin du script...
JJ
-
- Messages : 7967
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: HectorDuino
on sorte du while(1) avec cad qu'on sort (last), sauf si (unless), on a lu quelque chose ($read est impliciment non vide), cad lorsqu'on a atteint la fin de fichier source (IN).
Code : Tout sélectionner
my $read = read(IN,$buf,4096);
last unless $read;
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Re: HectorDuino
salut sam,
il me semblait aussi mais en mettant des print partout je ne comprend pas pourquoi lorsque l'on sort avec ce last on ne continu pas après le bloc : j'ai ajouté un print ici :
et le "fini" n’apparaît pas si le film fait plus de 3600 images (et donc pas de GIF créé).
Question : "LAST" permet de quitter la boucle while(1) mais immédiatement (comme en c) où il laisse le bloc continuer et sort uniquement lors du rebouclage du while ?
il me semblait aussi mais en mettant des print partout je ne comprend pas pourquoi lorsque l'on sort avec ce last on ne continu pas après le bloc : j'ai ajouté un print ici :
Code : Tout sélectionner
last if $cpt==3600;
}
}
print "fini !\n";
close(OUT);
unlink(<$ENV{'HOME'}/img*.bmp>);
Question : "LAST" permet de quitter la boucle while(1) mais immédiatement (comme en c) où il laisse le bloc continuer et sort uniquement lors du rebouclage du while ?
-
- Messages : 7967
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: HectorDuino
le "last" du perl est equivalent du "break;" en C: il quitte immédiatement la boucle dans laquelle il est appellé.
Si le print ne s'affiche pas, ca peut-être causé par un problème de bufferisation de la sortie.
Je me demande si je ne devrais pas transformer mes scripts perl en scripts LUA. Etant donné que lua est bien plus facile à installer que perl (l'interpréteur fait quelques centaines de ko seulement.)
Si le print ne s'affiche pas, ca peut-être causé par un problème de bufferisation de la sortie.
Je me demande si je ne devrais pas transformer mes scripts perl en scripts LUA. Etant donné que lua est bien plus facile à installer que perl (l'interpréteur fait quelques centaines de ko seulement.)
Dernière modification par __sam__ le 23 sept. 2017 20:16, modifié 1 fois.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Re: HectorDuino
ben c'est assez bizarre que selon le last utilisé (celui du read et celui du test de longueur) le print fonctionne ou pas...
de plus si je suis la dessus c'est que le GIF ne se créé pas si on sort par le read et il se créé si on sort par la limite du compteur...
de plus si je suis la dessus c'est que le GIF ne se créé pas si on sort par le read et il se créé si on sort par la limite du compteur...
-
- Messages : 7967
- Inscription : 18 sept. 2010 12:08
- Localisation : Brest et parfois les Flandres
Re: HectorDuino
ce qu'il serait possible c'est d'utiliser une variable "$ok" initialisée à 1 et l'on sort si $ok passe à 0.
Mais un truc à faire avant tout ca: passer le paramètre du READ de 4096 à 256. En effet il est possible que le fichier soit si petit que dans la lecture de 4096 on lise l'équivalent de toutes les images restantes, empêchant d'atteintre $cpt==3600. C'est à essayer du moins.
Code : Tout sélectionner
$ok = 1
while($ok) {
...
$ok = 0 unless $read; # était: last unless $read;
...
$ok = 0 if $cpt==3600; # était: last if $cpt==3600;
...
}
print "fini!\n";
close(OUT);
...
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Re: HectorDuino
Salut,
J'ai modifié le script avec la variable pour le while, ainsi que le buffer à 256. Pareil.
J'ai un doute sur le syswrite. J'ai fait un :
(c'est cocasse cette écriture!)
Mais c'est pareil : pas de suite si la sortie se réalise suite à la fin du traitement et correct si on réalise le LAST du nombre de frames.
il me semble que le : $ok = 0 unless $read;
ne fonctionne pas : Je fais un print $ok après cette ligne et même en fin de film le ok est à 1...
Edit :
pour moi le retour de read est le nombre d'octets soit 256. C'est d'ailleurs ce que je trouve en faisant un print $read qui me donne 256, même au dernier read, ce qui ne permet pas de sortir. Le "syswrite" planterait alors sur un buffer vide... ?
J'ai modifié le script avec la variable pour le while, ainsi que le buffer à 256. Pareil.
J'ai un doute sur le syswrite. J'ai fait un :
Code : Tout sélectionner
syswrite OUT, $buf, $read if ($ok==1);
Mais c'est pareil : pas de suite si la sortie se réalise suite à la fin du traitement et correct si on réalise le LAST du nombre de frames.
il me semble que le : $ok = 0 unless $read;
ne fonctionne pas : Je fais un print $ok après cette ligne et même en fin de film le ok est à 1...
Edit :
pour moi le retour de read est le nombre d'octets soit 256. C'est d'ailleurs ce que je trouve en faisant un print $read qui me donne 256, même au dernier read, ce qui ne permet pas de sortir. Le "syswrite" planterait alors sur un buffer vide... ?