IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Jouer un Son jusqu'à un évènement OnMouseDown


Sujet :

C++Builder

  1. #1
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut Jouer un Son jusqu'à un évènement OnMouseDown
    Bonjour à tous

    Pour un programme que je développe, je dois jouer un son à une certaine fréquence jusqu'à ce que l'on clique sur le bouton Gauche de la souris.

    La fonction BEEP permet de jouer un son de fréquence passé en paramètre ainsi qu'une durée.
    Je ne peux donc pas l'utiliser en état car moi c'est un évènement souris qui arrête le son et non une durée.

    J'ai donc créé un Thread dans lequel je lance le son avec une durée suffisamment grande pour ne pas que le son se coupe trop tôt.

    Et donc quand mon évènement souris se déclenche, je termine le Thread pour arrêter le son.

    Or le son ne s'arrête pas quand je clique sur la souris, il continu jusqu'à son terme avant d'effectuer ce qu'il y a dans la fonction de l'évènement souris.

    Auriez-vous une solution à mon problème.

    Voici mon code simplifié

    ThreadSon.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    //---------------------------------------------------------------------------
     
    #ifndef ThreadSonH
    #define ThreadSonH
     
    //---------------------------------------------------------------------------
     
    #include <System.Classes.hpp>
     
    //---------------------------------------------------------------------------
     
    class TThreadSon : public TThread
    {
    	private:
     
    		// Frequence
    		int Frequence;
     
    		// Duree
    		int Duree;
     
    	protected:
     
    		void __fastcall Execute();
     
     
    	public:
     
    		__fastcall TThreadSon(bool CreateSuspended, int F, int D);
    };
     
    //---------------------------------------------------------------------------
     
    #endif


    ThreadSon.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    //---------------------------------------------------------------------------
     
    #include <System.hpp>
    #pragma hdrstop
     
    #include "ThreadSon.h"
     
    #include "Principale.h"
     
     
    #pragma package(smart_init)
     
    //---------------------------------------------------------------------------
     
    //   Important : Les méthodes et les propriétés des objets de la VCL peuvent seulement être
    //   utilisées dans une méthode appelée avec Synchronize, par exemple :
    //
    //      Synchronize(&UpdateCaption);
    //
    //   où UpdateCaption pourrait ressembler à :
    //
    //      void __fastcall TThreadSon::UpdateCaption()
    //      {
    //        Form1->Caption = "Mis à jour dans un thread";
    //      }
    //---------------------------------------------------------------------------
     
    __fastcall TThreadSon::TThreadSon(bool CreateSuspended, int F, int D)
    	: TThread(CreateSuspended), Frequence(F), Duree(D)
    {
    	// on marque que le Thread se détruit tout seul
    	FreeOnTerminate = true;
    }
     
    //---------------------------------------------------------------------------
     
    void __fastcall TThreadSon::Execute()
    {
    	//---- Placer le code du thread ici ----
    	// On joue le Son
    	Beep(Frequence, Duree);
    }
     
    //---------------------------------------------------------------------------
    Code Principal
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    // Voici comment je lance mon Son
    ThreadSon = new TThreadSon(false, Frequence, 10000);
     
    // Méthode déclenchée lorsqu'on appuie sur le bouton de la Souris
    void __fastcall TAffichageForm::OnMouseDown(TObject *Sender, TMouseButton Button,
    		  TShiftState Shift, float X, float Y)
    {
    	// Si le bouton Gauche est enfoncé
    	if(Button == TMouseButton::mbLeft)
    	{
    		// Si le Thread son est en route
    		if(ThreadSon)
    		{
    			// on termine le Thread
    			ThreadSon->Terminate();
    		}
    	}
    }
    Merci d'avance pour votre aide

  2. #2
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Dans le code que tu as écrit, le thread ne fait pas grand chose. Il lance le beep() et se termine immédiatement, quand après tu appelles Terminate() il est déjà fini depuis longtemps. Quant au beep, il continue son boulot!
    Tu a besoin d'une commande pour stopper le beep(). Peut-être qu'un nouveau beep() de durée 0 pourrait le préempter? Je ne connais pas C++Builder pour t'aider.

  3. #3
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Pas sûr qu'il soit possible d'interrompre l'exécution de la fonction Beep une fois lancée ...

    Si la liste des fréquences que tu dois jouer n'est pas trop grande, moi je me tournerais plutôt vers la lecture de fichiers son avec un TMediaPlayer.
    Sinon, peut-être les commandes MIDI ... ou l'utilisation d'une bibliothèque de gestion audio (https://www.un4seen.com/) ...
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  4. #4
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Merci pour vos réponse.

    Mon souci c'est que je ne sais pas à l'avance quelle fréquence sera utilisée car c'est un paramètre que les utilisateurs doivent rentrer.

    Pour le Thread, je pensais qu'il se terminait quand le Beep avait fini son temps (FreeOnTerminate dans le constructeur). Du coup effectivement s'il est terminé, c'est normal que le beep continu.

    Je vais regarder ce que cela donne en envoyant un nouveau Beep de 0

    Après construire des son, cela va me demander beaucoup de temps et je n'en ai pas car je dois livrer le logiciel rapidement

  5. #5
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Je reviens vers vous car ta solution dalfab fonctionne.

    Effectivement un Beep de 0 arrête l'autre beep du coup cela fait exactement ce que je veux.

    Par contre je laisse bien le Beep dans le Thread car sinon cela bloque mon programme si je le met direct.

    Merci à vous deux pour avoir répondu

  6. #6
    Membre éprouvé
    Femme Profil pro
    ..
    Inscrit en
    Décembre 2019
    Messages
    562
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 94
    Localisation : Autre

    Informations professionnelles :
    Activité : ..

    Informations forums :
    Inscription : Décembre 2019
    Messages : 562
    Points : 1 253
    Points
    1 253
    Par défaut
    Salut,

    Si c'est un programme que tu dois livrer, il faut faire attention car s'il est lancé sur un Windows 64bits, la fonction Beep() risque de ne pas produire le résultat escompté, ou ne rien produire du tout.

    @dalfab, la fonction Beep() est bloquante. Si le thread ne répond pas immédiatement au Terminate() c'est parce qu'il n'y est pas obligé, en plus du fait que c'est le genre de fonction dont l'usage doit être absolument évité.

  7. #7
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Citation Envoyé par kaitlyn Voir le message
    Salut,
    Si c'est un programme que tu dois livrer, il faut faire attention car s'il est lancé sur un Windows 64bits, la fonction Beep() risque de ne pas produire le résultat escompté, ou ne rien produire du tout.
    C'est un programme en Win32 donc pas de souci de ce côté là.

    Citation Envoyé par kaitlyn Voir le message
    @dalfab, la fonction Beep() est bloquante. Si le thread ne répond pas immédiatement au Terminate() c'est parce qu'il n'y est pas obligé, en plus du fait que c'est le genre de fonction dont l'usage doit être absolument évité.
    Effectivement et c'est là que finalement je croyais avoir résolu mon problème mais en fait non. Le beep de 0 annule bien le beep au niveau sonore mais n'arrête pas le Thread pour autant. du coup les Threads s'empilent et s'arrêtent quand ils ont terminés le temps du Beep et du coup au bou d'un moment, et bien cela arrête les beep suivants avant qu'ils soient terminés, ce qui me pose problème.

    J'ai essayé en appelant terminate sur le Thread mais aucun effet étant donné que le beep est bloquant.
    J'ai aussi essayé en tuant directement le thread par un delete, cela arrête bien le Thread mais ça bloque mon programme ensuite.

    Du coup je ne sais pas comment faire car la durée du beep n'est pas fixe, le beep doit s'arrêter par un clic de souris.

    Avez-vous des idées ?

  8. #8
    Membre actif Avatar de Argol_Medusa
    Homme Profil pro
    Ingénieur Radiofréquences
    Inscrit en
    Août 2005
    Messages
    208
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Radiofréquences
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 208
    Points : 242
    Points
    242
    Par défaut
    Perso je créerai au moment du choix de la fréquence par l'utilisateur un fichier .WAV avec une sinusoidale dedans ( très facile à en calculer les points ) et après je jouerai ce fichier avec un TMediaPlayer.
    Et là tu peux faire un stop quand tu veux.
    Et peut-etre même plus besoin de thread non plus.
    Désolé, on savait pas que c'était impossible, alors on l'a fait

  9. #9
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Merci pour ta réponse Argol_Medusa

    J'y est pensé, la partie lancement et arrêt avec le MediaPlayer je maitrise, mais par contre je ne sais pas comment faire pour créer mon fichier WAV. Pourrais-tu m'expliquer comment tu fait s'il te plait.

  10. #10
    Membre actif Avatar de Argol_Medusa
    Homme Profil pro
    Ingénieur Radiofréquences
    Inscrit en
    Août 2005
    Messages
    208
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Radiofréquences
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 208
    Points : 242
    Points
    242
    Par défaut
    Oui, il faut créer un header et après tu mets tes échantillons les uns après les autres.

    Je l'avais fait je vais essayer de retrouver le code pour te montrer un exemple.
    Désolé, on savait pas que c'était impossible, alors on l'a fait

  11. #11
    Membre confirmé Avatar de kurul1
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    933
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 933
    Points : 466
    Points
    466
    Par défaut
    Merci Argol_Medusa pour ton aide mais t’embêtes pas, je viens de trouver ceci qui fait le job

    wavfile.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    /*
    A simple sound library for CSE 20211 by Douglas Thain.
    This work is made available under the Creative Commons Attribution license.
    https://creativecommons.org/licenses/by/4.0/
     
    For course assignments, you should not change this file.
    For complete documentation, see:
    http://www.nd.edu/~dthain/courses/cse20211/fall2013/wavfile
    */
     
    #ifndef WAVFILE_H
    #define WAVFILE_H
     
    #include <stdio.h>
    #include <inttypes.h>
     
    FILE * wavfile_open( const char *filename );
    void wavfile_write( FILE *file, short data[], int length );
    void wavfile_close( FILE * file );
     
    #define WAVFILE_SAMPLES_PER_SECOND 44100
     
    #endif
    wavfile.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
     
    /*
    A simple sound library for CSE 20211 by Douglas Thain (dthain@nd.edu).
    This work is made available under the Creative Commons Attribution license.
    https://creativecommons.org/licenses/by/4.0/
     
    For course assignments, you should not change this file.
    For complete documentation, see:
    http://www.nd.edu/~dthain/courses/cse20211/fall2013/wavfile
    */
     
    #include "wavfile.h"
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    struct wavfile_header {
    	char	riff_tag[4];
    	int	riff_length;
    	char	wave_tag[4];
    	char	fmt_tag[4];
    	int	fmt_length;
    	short	audio_format;
    	short	num_channels;
    	int	sample_rate;
    	int	byte_rate;
    	short	block_align;
    	short	bits_per_sample;
    	char	data_tag[4];
    	int	data_length;
    };
     
    FILE * wavfile_open( const char *filename )
    {
    	struct wavfile_header header;
     
    	int samples_per_second = WAVFILE_SAMPLES_PER_SECOND;
    	int bits_per_sample = 16;
     
    	strncpy(header.riff_tag,"RIFF",4);
    	strncpy(header.wave_tag,"WAVE",4);
    	strncpy(header.fmt_tag,"fmt ",4);
    	strncpy(header.data_tag,"data",4);
     
    	header.riff_length = 0;
    	header.fmt_length = 16;
    	header.audio_format = 1;
    	header.num_channels = 1;
    	header.sample_rate = samples_per_second;
    	header.byte_rate = samples_per_second*(bits_per_sample/8);
    	header.block_align = bits_per_sample/8;
    	header.bits_per_sample = bits_per_sample;
    	header.data_length = 0;
     
    	FILE * file = fopen(filename,"wb+");
    	if(!file) return 0;
     
    	fwrite(&header,sizeof(header),1,file);
     
    	fflush(file);
     
    	return file;
     
    }
     
    void wavfile_write( FILE *file, short data[], int length )
    {
    	fwrite(data,sizeof(short),length,file);
    }
     
    void wavfile_close( FILE *file )
    {
    	int file_length = ftell(file);
     
    	int data_length = file_length - sizeof(struct wavfile_header);
    	fseek(file,sizeof(struct wavfile_header) - sizeof(int),SEEK_SET);
    	fwrite(&data_length,sizeof(data_length),1,file);
     
    	int riff_length = file_length - 8;
    	fseek(file,4,SEEK_SET);
    	fwrite(&riff_length,sizeof(riff_length),1,file);
     
    	fclose(file);
    }
    Le fichier example.c pour l'utilisation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    /*
    This example program makes use of the simple
    sound library to generate a sine wave and write the
    output to sound.wav.
    For complete documentation on the library, see:
    http://www.nd.edu/~dthain/courses/cse20211/fall2013/wavfile
    Go ahead and modify this program for your own purposes.
    */
     
     
    #include <stdio.h>
    #include <math.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #include <errno.h>
     
    #include "wavfile.h"
     
     
    int main()
    {
    	short waveform[NUM_SAMPLES];
    	double frequency = 440.0;
    	int volume = 32000;
    	int length = NUM_SAMPLES;
     
    	int i;
    	for(i=0;i<length;i++) {
    		double t = (double) i / WAVFILE_SAMPLES_PER_SECOND;
    		waveform[i] = volume*sin(frequency*t*2*M_PI);
    	}
     
    	FILE * f = wavfile_open("sound.wav");
    	if(!f) {
    		printf("couldn't open sound.wav for writing: %s",strerror(errno));
    		return 1;
    	}
     
    	wavfile_write(f,waveform,length);
    	wavfile_close(f);
     
    	return 0;
    }
    C'est en C mais je l'ai adapté pour que cela tourne sous C++ et cela fonctionne bien.
    J'ai rencontré seulement un petit souci pour la durée du fichier. Dans ce code on créé un fichier de 2 sec (définit par la ligne
    const int NUM_SAMPLES = (WAVFILE_SAMPLES_PER_SECOND*2); ), or moi j'avais besoin d'un fichier de 3 Minutes, soit 180 secondes et du coup cela plantait.

    J'ai résolu le problème en créant un échantillon de 1 seconde ou lieu de 2 et ensuite lors de l'écriture, je l'écrit 180 fois et c'est tout bon.

    Et du coup maintenant je lit mon fichier généré que j'arrête lorsque l'évènement de souris survient et voilà.

    Merci à tous pour votre aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [C#] Créer son journal d'évènement perso
    Par globeriding dans le forum ASP.NET
    Réponses: 17
    Dernier message: 16/01/2006, 22h56
  2. [Audio]Jouer un son .au
    Par Pill_S dans le forum Multimédia
    Réponses: 11
    Dernier message: 28/12/2004, 17h46
  3. DIRECT MUSIC / JOUER DEUX SONS OU PLUS..
    Par ilimo dans le forum DirectX
    Réponses: 1
    Dernier message: 12/06/2004, 18h24
  4. Jouer un son MIDI
    Par Slock dans le forum Langage
    Réponses: 3
    Dernier message: 26/11/2003, 10h02
  5. Existe t'il un composant permettant de jouer un son wav?
    Par scorpiwolf dans le forum C++Builder
    Réponses: 5
    Dernier message: 20/06/2002, 14h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo