Cambiare volume di un segnale durante il play

di il
8 risposte

Cambiare volume di un segnale durante il play

Ciao a tutti! Devo fare un progetto per l'università nel quale mi si chiede di cambiare dinamicamente l'ampiezza di un'onda tramite un pulsante che la raddoppia e uno che la dimezza.
Ho tentato di fare così:

sound(A*do4,Fs,Nbit);
                   edit=menu('','V+','V-');
                       switch edit
                           case 1%V+
                               if A~=1
                                   A=A*2; 
                               end
                           case 2%V-
                               A=A/2;        
                       end
e l'ampiezza me la modifica anche lui, ma dopo che sound ha finito mentre io vorrei che appena schiaccio il pulsante V+ o V-, mentre l'audio sta ancora suonando, mi si modifichi la sua ampiezza di riproduzione...

Come posso fare?
Grazie mille!

8 Risposte

  • Re: Cambiare volume di un segnale durante il play

    Una possibile soluzione:

    http://www.mathworks.com/matlabcentral/newsreader/view_thread/154000

    Hope this helps.
  • Re: Cambiare volume di un segnale durante il play

    Grazie mille! ora provo a smanettare un po? ma l handle cos é? e come si definisce?

    Ho letto poi che quel metodo è valido solo per una modifica di volume alla volta... non c'è qualcosa di un po più generico? oppure un modo per sovrascrivere il player con un segnale amplificato?
  • Re: Cambiare volume di un segnale durante il play

    Ho trovato una soluzione per il controllo del volume qui:

    http://www.mathworks.com/matlabcentral/fileexchange/25584-soundvolume-set-or-get-the-system-speaker-sound-volume

    Il codice sorgente è qui:

    http://www.mathworks.com/matlabcentral/fileexchange/25584-soundvolume-set-or-get-the-system-speaker-sound-volume/content/SoundVolume.m

    Ho provato a costruire una semplice GUI con un pushbutton che avvia la riproduzione usando la funzione "sound" (ho usato l'esempio fornito dall'help di MatLab) e uno slider per il controllo del volume.

    Per quanto riguarda lo slider, ho settato (tramite GUIDE, ma si può fare anche usando la funzione set)i parametri:
    
    Max=1
    Min=0
    Value=1
    
    I parametri Max e Min rappresentano, rispettivamente, il valore massimo e quello minimo ritornato dallo slider.
    Il range (0;1) è richiesto dalla funzione "SoundVolume": 0 corrisponde al valore minimo del volume, 1 al valore massimo.

    All'apertura della GUI, lo slider sarà quindi inizializzato al valore massimo.

    Nella callback del pushbutton per l'attivazione della riproduzione ho inserito:
    load handel
    sound(y,Fs)
    
    Nella callback dello slider ho inserito:
    
    new_vol=get(hObject,'Value');
    SoundVolume(new_vol)
    
    Sembra che funzioni

    Hope this helps.
  • Re: Cambiare volume di un segnale durante il play

    Come ti ho ringraziato anche nell'altro mio post grazie infinite anche qua perchè il volume ora funziona benissimo! se posso vorrei chiederti un'ultima cosa:
    dalla gui dove estraggo il nuovo volume vorrei memorizzare tutto il mio inviluppo di volume in un array per poi mandarlo allo "script principale" dal quale ho richiamato la gui
    (la mia applicazione è simulare una tastiera musicale dove ad ogni nota schiacciata richiamo la gui con la quale posso controllare in tempo reale il volume della nota).
    Ho pensato quindi di memorizzare ogni valore dello slide in una cella di varargout e nello script principale mettere:
     inviluppo=gui;   //nella mia testa inviluppo sarà uguale a varargout giusto?
    Il problema è che sia che mi da questo errore quando viene richiamata la gui:

    Error: File: gui_nota.m Line: 86 Column: 1
    "varargout" previously appeared to be used as a function or command, conflicting with its use here as the name of a variable.
    A possible cause of this error is that you forgot to initialize the variable, or you have initialized it implicitly using load or eval.


    Error in progettoEsame (line 72)
    inviluppo_nota=gui_nota;

    Nel file.m della gui per riempire l'array varargout ho fatto così:
    
    new_vol=get(hObject,'Value');
    i=length(varargout)+1
    varargout{i}=new_vol;
    SoundVolume(new_vol);
    
    dove con varargout ho provato sia con le {} sia con le []

    Dove sbaglio? Grazie ancora
  • Re: Cambiare volume di un segnale durante il play

    Mattia541993 ha scritto:


    Ho pensato quindi di memorizzare ogni valore dello slide in una cella di varargout e nello script principale mettere:
     inviluppo=gui;   //nella mia testa inviluppo sarà uguale a varargout giusto?
    Non mi è chiara la struttura del programma, mi sembra aver capito che c'è un "main" costituito da un file ".m" che "chiama" la funzione che genera e gestisce la GUI.
    Se è così, il main è uno script od una funzione?

    Per poter provare a dare una risposta efficace, sarebbe utile avere il codice completo dello script principale e della GUI (ammesso che siano due files diversi) per verificare come è stata impostata la funzione che utilizza "varargout".
    Cosa è "gui"?
    Cosa è "inviluppo"?

    Mattia541993 ha scritto:


    Nel file.m della gui per riempire l'array varargout ho fatto così:
    
    new_vol=get(hObject,'Value');
    i=length(varargout)+1
    varargout{i}=new_vol;
    SoundVolume(new_vol);
    
    dove con varargout ho provato sia con le {} sia con le []
    Dove sbaglio? Grazie ancora
    Anche per rispondere a questa domanda serve avere il codice della GUI.

  • Re: Cambiare volume di un segnale durante il play

    Questo è il codice che richiama la GUI (è in uno switch case)

    il codice principale è uno script e gui è il richiamo al file .m generato da GUIDE
    
    %Progetto d'esame Mattia Ducci
    
    clear;
    close all;
    
    
    %-----------Scelta del metodo (sintesi o registrazione o test)-------------
    
    metodo=menu('Scegli il metodo operativo','Sintesi','Test');
    
    %-----------Esecuzione del metodo scelto--------------------------
    
    switch metodo
        case 1%sintesi
            
            %setup dominio digitale
            Fs=44100;
            Ts=1/Fs;
            Nbit=16;
            AdB=0;
            A=10^(AdB/20);
            Fc=10000;%di default imposto una freq taglio alta(Hz)
            %creo a priori i miei campioni di note
            AddToReg=0;
            NotPlay=0;%riconosce se ho schiacciato il pulsante play
            global inviluppo_nota;
            inviluppo_nota=0;
            %------------------------DO4-------------------
            Fdo4=261.6;
             for n=1:Fs
                 do4(n)=A*sin(2*pi*Fdo4*n*Ts)+A/2*sin(2*pi*(3*Fdo4)*n*Ts)+A/3*sin(2*pi*(5*Fdo4)*n*Ts)+A/5*sin(2*pi*(7*Fdo4)*n*Ts);
             end
              %------------------------RE-------------------
            Fre=293.7;
             for n=1:Fs
                 re(n)=A*sin(2*pi*Fre*n*Ts)+A/2*sin(2*pi*(3*Fre)*n*Ts)+A/3*sin(2*pi*(5*Fre)*n*Ts)+A/5*sin(2*pi*(7*Fre)*n*Ts);
             end
              %------------------------MI-------------------
            Fmi=329.6;
             for n=1:Fs
                 mi(n)=A*sin(2*pi*Fmi*n*Ts)+A/2*sin(2*pi*(3*Fmi)*n*Ts)+A/3*sin(2*pi*(5*Fmi)*n*Ts)+A/5*sin(2*pi*(7*Fmi)*n*Ts);
             end
              %------------------------FA-------------------
            Ffa=349.2;
             for n=1:Fs
                 fa(n)=A*sin(2*pi*Ffa*n*Ts)+A/2*sin(2*pi*(3*Ffa)*n*Ts)+A/3*sin(2*pi*(5*Ffa)*n*Ts)+A/5*sin(2*pi*(7*Ffa)*n*Ts);
             end
              %------------------------SOL-------------------
            Fsol=261.6;
             for n=1:Fs
                 sol(n)=A*sin(2*pi*Fsol*n*Ts)+A/2*sin(2*pi*(3*Fsol)*n*Ts)+A/3*sin(2*pi*(5*Fsol)*n*Ts)+A/5*sin(2*pi*(7*Fsol)*n*Ts);
             end
             %------------------------LA-------------------
            Fla=440;
             for n=1:Fs
                 la(n)=A*sin(2*pi*Fla*n*Ts)+A/2*sin(2*pi*(3*Fla)*n*Ts)+A/3*sin(2*pi*(5*Fla)*n*Ts)+A/5*sin(2*pi*(7*Fla)*n*Ts);
             end
              %------------------------SI-------------------
            Fsi=493.9;
             for n=1:Fs
                 si(n)=A*sin(2*pi*Fsi*n*Ts)+A/2*sin(2*pi*(3*Fsi)*n*Ts)+A/3*sin(2*pi*(5*Fsi)*n*Ts)+A/5*sin(2*pi*(7*Fsi)*n*Ts);
             end
              %------------------------DO5-------------------
            Fdo5=523.2;
             for n=1:Fs
                 do5(n)=A*sin(2*pi*Fdo5*n*Ts)+A/2*sin(2*pi*(3*Fdo5)*n*Ts)+A/3*sin(2*pi*(5*Fdo5)*n*Ts)+A/5*sin(2*pi*(7*Fdo5)*n*Ts);
             end
             exec=1;%variabile che abilita la continuazione dell'esecuzione
            while(exec==1)
                azione=menu('Scegli cosa fare:','C/Do','D/Re','E/Mi','F/Fa','G/Sol','A/La','B/Si','C/Do', 'V+', 'V-', 'Trebles up', 'Trebles down','Termina','Play');
                switch azione
                    %x tutte le note genero un'onda quadra(armoniche dispari
                    %decrescenti, 1s per ogni pressione di tasto hai i
                    %puffi!!!!nooooooooooooooooooooooooooooooooooooooo
                    case 1%Do
                        controllo_gui=gui_nota;
                        %creo un Do tenendo conto delle impostazioni di
                        %filtraggio
                        a=1-exp(-2*pi*(Fc/Fs)); % First filter coefficent. FORMULA DEL PASSA BASSO
                        b=1-a;                  % Second filter coefficent
                        ydo4(1)=0;       % Filter memory (starts as zero)
                        n=2;  
                    while n <= length(do4)   
                        ydo4(n)=A*(a*do4(n)+b*ydo4(n-1));
                        n=n+1;
                    end 
                        %--------RIPRODUZIONE SUONO SECONDO PARAMETRI FILTRAGGIO E AMPIEZZA------------ 
                       %sound(A*ydo4,Fs,Nbit);
                       if NotPlay==0
                       player=audioplayer(ydo4,Fs,Nbit);
                       play(player);
                       end
                       if AddToReg==0
                           S=ydo4;%S è la registrazione
                           AddToReg=1;
                       elseif AddToReg==1
                           S=[S,ydo4];
                       else
                           1;
                       end
                       
                       
                        
                    case 2%Re
                       
                    case 3%Mi
                      
                    case 4%Fa
                       
                    case 5%Sol
                      
                    case 6%La
                      
                    case 7%Si
                       
                    case 8%Do
                      
                    case 9%V+
                            if A~=1
                               A=A*2; 
                            end 
                    case 10%V-
                        A=A/2;
                        
                    case 11%Trebles up->Fc up
                        if Fc<Fs/2;
                         Fc=Fc*2;
                        end
                        
                    case 12%Trebles down->Fc down
                        if Fc>0;
                        Fc=Fc/2;
                        end
                        
                    case 13%Termina
                        exec=0;
                        
                    case 14%Play
                        AddToReg=2;
                        NotPlay=1;
                        sound(S,Fs,Nbit);
                        plot(S);
                        NotPlay=0;
                        AddToReg=0;%in modo che ogni volta che riproduco la rec viene cancellata
                    
                end
                
            end
    
  • Re: Cambiare volume di un segnale durante il play

    Leggendo lo script, l'unico punto nel quale mi sembra che venga chiamata la GUI che controlla il volume è

    controllo_gui=gui_nota;

    se è così non mi è chiaro quale suono riproduca e, quindi, come vengano cambiati i valori del volume.

    Ad ogni modo, se la domanda è: come esportare dalla GUI che consente di regolare il volume con uno slider, spero che quanto segue risponda alla tua domanda.

    La procedura consiste nell'aggiungere del codice in diverse funzioni e callback della GUI come di seguito riportato.
    I valori vengono esportati quando la GUI viene chiusa.

    Le modifiche / aggiunte sono racchiuse tra due righe di "%"

    %%%%%%%%%%%%%%%%%

    %%%%%%%%%%%%%%%%%

    (*)(tieni presente che, purtroppo, non uso MatLab 2015, per cui, non posso garantirti che le istruzioni che seguono funzionino direttamente in MatLab 2015 - potrebbe essere necessario apportare qualche modifica).

    (*) nel seguito, XXX_ è il nome della GUI

    function play_m_OpeningFcn(hObject, eventdata, handles, varargin)
    
    % --- Executes just before play_m is made visible.
    function play_m_OpeningFcn(hObject, eventdata, handles, varargin)
    % This function has no output args, see OutputFcn.
    % hObject    handle to figure
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    % varargin   command line arguments to play_m (see VARARGIN)
    
    % Choose default command line output for play_m
    handles.output = hObject;
    
    % Update handles structure
    guidata(hObject, handles);
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Definizione della struttura che memorizza i dati della GUI
    gui_my_data=guidata(handles.figure1)
    % Inizializzazione del contatore degli elementi del vettore che contiene i
    % settaggi del volume
    gui_my_data.vol_cnt=0;
    % Inizializzazione del vettore che contiene i settaggi del volume
    gui_my_data.volume_settings=[];
    % Aggiornaento della struttura dati della GUI
    guidata(handles.figure1,gui_my_data)
    
    load handel
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    % UIWAIT makes play_m wait for user response (see UIRESUME)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Questa istruzione è stata "scommentata" (di default dovrebbe essere
    % commentata
    uiwait(handles.figure1);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    function varargout = play_m_OutputFcn(hObject, eventdata, handles)
    
    % --- Outputs from this function are returned to the command line.
    function varargout = play_m_OutputFcn(hObject, eventdata, handles) 
    % varargout  cell array for returning output args (see VARARGOUT);
    % hObject    handle to figure
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Get default command line output from handles structure
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Questa istruzione è stata commentata
    % varargout{1} = handles.output;
    
    % Acquisizione della struttura che memorizza i dati della GUI
    gui_my_data=guidata(handles.figure1)
    % Assegnazione del vettore contgenente i settaggi del volume alla variabile
    % "varargout". Questo sarà il valore ritornato dalla GUI
    varargout{1} = gui_my_data.volume_settings;
    % Chiusura della GUI
    delete(hObject);
    
    function slider1_Callback(hObject, eventdata, handles) (callback per la gestione dello slider
    
    % --- Executes on slider movement.
    function slider1_Callback(hObject, eventdata, handles)
    % hObject    handle to slider1 (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Hints: get(hObject,'Value') returns position of slider
    %        get(hObject,'Min') and get(hObject,'Max') to determine range of slider
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    % Acquisizione del valore dello slider
    act_vol=get(hObject,'Value');
    % Chiamata della funzione che regola il volume
    SoundVolume(act_vol)
    % Acquisizione dati GUI
    gui_my_data=guidata(handles.figure1)
    % Incremento del contatore dei settaggi del volume
    vol_cnt=gui_my_data.vol_cnt+1;
    % Memorizzazione dell'i-esimo settaggio del volume nel vettore della
    % struttura dati della GUI
    gui_my_data.volume_settings(vol_cnt)=act_vol;
    % Memorizzazione del contatore dei settaggi del volume nella struttura dati
    % della GUI
    gui_my_data.vol_cnt=vol_cnt;
    % Aggiornamento della struttura dati della GUI
    guidata(handles.figure1,gui_my_data)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    function figure1_CloseRequestFcn(hObject, eventdata, handles)
    
    % --- Executes when user attempts to close figure1.
    function figure1_CloseRequestFcn(hObject, eventdata, handles)
    % hObject    handle to figure1 (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Hint: delete(hObject) closes the figure
    uiresume(hObject);
    % delete(hObject);
    
    function figure1_CloseRequestFcn(hObject, eventdata, handles)
    
    % --- Executes when user attempts to close figure1.
    function figure1_CloseRequestFcn(hObject, eventdata, handles)
    % hObject    handle to figure1 (see GCBO)
    % eventdata  reserved - to be defined in a future version of MATLAB
    % handles    structure with handles and user data (see GUIDATA)
    
    % Hint: delete(hObject) closes the figure
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    uiresume(hObject);
    % delete(hObject);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    Con le modifiche apportate alle funzioni automaticamente create da GUIDE:
    OpeningFcn
    OutputFcn
    CloseRequestFcn

    ed alla callback per la gestione dello slider:
    slider1_Callback

    invocando la GUI in uno script:

    ret_vat=my_gui

    quando la GUI viene chiusa, nel vettore "ret_vat" saranno memorizzati i valori assunti dallo slider per il controllo del volume.

    Si possono trovare informazioni ed un esempio qui:

    http://blogs.mathworks.com/videos/2010/02/12/advanced-getting-an-output-from-a-guide-gui/

    Mi rendo conto che è un po' complicato e che probabilmente la spiegazione potrebbe essere migliore, tuttavia ...

    Un suggerimento per lo script che hai inserito:

    Puoi notevolmente velocizzare la sezione che costruisce i vettori do4, re, mi ecc. se sostituisci tutta la serie di cicli for con le seguenti istruzioni:
    
            %------------------------DO4-------------------
            n=1:Fs;
            Fdo4=261.6;
             do4=A*sin(2*pi*Fdo4*n*Ts)+A/2*sin(2*pi*(3*Fdo4)*n*Ts)+A/3*sin(2*pi*(5*Fdo4)*n*Ts)+A/5*sin(2*pi*(7*Fdo4)*n*Ts);
              %------------------------RE-------------------
            Fre=293.7;
             re=A*sin(2*pi*Fre*n*Ts)+A/2*sin(2*pi*(3*Fre)*n*Ts)+A/3*sin(2*pi*(5*Fre)*n*Ts)+A/5*sin(2*pi*(7*Fre)*n*Ts);
              %------------------------MI-------------------
            Fmi=329.6;
             mi=A*sin(2*pi*Fmi*n*Ts)+A/2*sin(2*pi*(3*Fmi)*n*Ts)+A/3*sin(2*pi*(5*Fmi)*n*Ts)+A/5*sin(2*pi*(7*Fmi)*n*Ts);
              %------------------------FA-------------------
            Ffa=349.2;
             fa=A*sin(2*pi*Ffa*n*Ts)+A/2*sin(2*pi*(3*Ffa)*n*Ts)+A/3*sin(2*pi*(5*Ffa)*n*Ts)+A/5*sin(2*pi*(7*Ffa)*n*Ts);
              %------------------------SOL-------------------
            Fsol=261.6;
             sol=A*sin(2*pi*Fsol*n*Ts)+A/2*sin(2*pi*(3*Fsol)*n*Ts)+A/3*sin(2*pi*(5*Fsol)*n*Ts)+A/5*sin(2*pi*(7*Fsol)*n*Ts);
             %------------------------LA-------------------
            Fla=440;
             la=A*sin(2*pi*Fla*n*Ts)+A/2*sin(2*pi*(3*Fla)*n*Ts)+A/3*sin(2*pi*(5*Fla)*n*Ts)+A/5*sin(2*pi*(7*Fla)*n*Ts);
              %------------------------SI-------------------
            Fsi=493.9;
             si=A*sin(2*pi*Fsi*n*Ts)+A/2*sin(2*pi*(3*Fsi)*n*Ts)+A/3*sin(2*pi*(5*Fsi)*n*Ts)+A/5*sin(2*pi*(7*Fsi)*n*Ts);
              %------------------------DO5-------------------
            Fdo5=523.2;
             do5=A*sin(2*pi*Fdo5*n*Ts)+A/2*sin(2*pi*(3*Fdo5)*n*Ts)+A/3*sin(2*pi*(5*Fdo5)*n*Ts)+A/5*sin(2*pi*(7*Fdo5)*n*Ts);
    
    
    Hope this helps.
  • Re: Cambiare volume di un segnale durante il play

    Chiarissimo!! Grazie!
Devi accedere o registrarti per scrivere nel forum
8 risposte