% Program pro hraní tónů pomocí klávesnice % MKS_01b.a % Na začátku si vyrobíme 13 půltónově vzdálených sinusových tónů délky % půl sekundy a klávesami pak pouze vybíráme, který z nich přehrajeme. % MAGNETOFON je až další vrstva: pamatuje si, který k jsem kdy stiskl, % a z těchto tónů potom složí nahrávku. % Jednoduchá výuková verze s "magnetofonem": % REC ... začne zaznamenávat stisky kláves % STOP ... ukončí záznam % PLAY ... přehraje zaznamenanou sekvenci % SAVE ... uloží sekvenci do WAV % % Každý tón má pevnou délku T. %------------------------------------------------------------- % vytvoření chromatické stupnice %------------------------------------------------------------- clear all close all clc % zvolte typ klávesnice: keyboardType = 'QWERTZ'; if strcmpi(keyboardType,'QWERTZ') notes = 'awsedftgzhujk'; else notes = 'awsedftgyhujk'; end Fe = 22050; f0 = 220; ht = 2^(1/12); fr = ht.^(0:12)*f0; T = 0.5; for k = 1:13 tones{k} = instrument(fr(k),T,Fe); end %------------------------------------------------------------- % okno %------------------------------------------------------------- fig = figure( ... 'Name','SYN LAB', ... 'NumberTitle','off', ... 'MenuBar','none', ... 'ToolBar','none', ... 'Position',[450 300 700 300], ... 'WindowKeyPressFcn',@keyPressed); axis([0 1 0 1]) axis off text(0.5,0.82,'SYN LAB', ... 'HorizontalAlignment','center','FontSize',18,'FontWeight','bold'); text(0.5,0.67,upper(notes), ... 'HorizontalAlignment','center','FontSize',14); text(0.5,0.57,'Hrajte přímo na klávesnici', ... 'HorizontalAlignment','center','FontSize',10); %------------------------------------------------------------- % magnetofon %------------------------------------------------------------- uicontrol(fig,'Style','pushbutton', ... 'String','REC', ... 'Position',[120 45 90 35], ... 'Callback',@recButton); uicontrol(fig,'Style','pushbutton', ... 'String','STOP', ... 'Position',[225 45 90 35], ... 'Callback',@stopButton); uicontrol(fig,'Style','pushbutton', ... 'String','PLAY', ... 'Position',[330 45 90 35], ... 'Callback',@playButton); uicontrol(fig,'Style','pushbutton', ... 'String','SAVE WAV', ... 'Position',[435 45 110 35], ... 'Callback',@saveButton); statusText = uicontrol(fig,'Style','text', ... 'String','MAGNETOFON: připraven', ... 'Position',[180 95 340 25], ... 'FontSize',10); %------------------------------------------------------------- % data programu %------------------------------------------------------------- data.notes = notes; data.tones = tones; data.Fe = Fe; data.T = T; data.recording = false; data.recordStart = []; data.events = []; % sloupec 1 = číslo tónu, sloupec 2 = čas stisku data.recordedSignal = []; data.statusText = statusText; guidata(fig,data); %========================================================================== % lokální funkce %========================================================================== function out = instrument(f,T,fs) t = 0:1/fs:T-1/fs; envelope = ones(1,length(t)); out = envelope .* sin(2*pi*f*t); end function keyPressed(src,event) data = guidata(src); key = lower(event.Character); if numel(key) ~= 1 return end k = find(data.notes == key,1); if isempty(k) return end % přehraj tón sound(data.tones{k},data.Fe) % pokud běží záznam, uložíme číslo tónu a čas stisku if data.recording tNow = toc(data.recordStart); data.events(end+1,:) = [k tNow]; guidata(src,data); end end function recButton(src,~) fig = ancestor(src,'figure'); data = guidata(fig); data.recording = true; data.recordStart = tic; data.events = []; data.recordedSignal = []; set(data.statusText,'String','MAGNETOFON: ● REC'); guidata(fig,data); end function stopButton(src,~) fig = ancestor(src,'figure'); data = guidata(fig); data.recording = false; if isempty(data.events) set(data.statusText,'String','MAGNETOFON: žádný záznam'); guidata(fig,data); return end % vytvoření výsledného zvukového signálu lastStart = data.events(end,2); N = round((lastStart + data.T)*data.Fe); y = zeros(1,N); for n = 1:size(data.events,1) k = data.events(n,1); t0 = data.events(n,2); i1 = round(t0*data.Fe) + 1; i2 = min(i1 + length(data.tones{k}) - 1,N); L = i2-i1+1; y(i1:i2) = y(i1:i2) + data.tones{k}(1:L); end % normalizace při souběhu tónů m = max(abs(y)); if m > 1 y = y/m; end data.recordedSignal = y; set(data.statusText,'String','MAGNETOFON: ■ STOP'); guidata(fig,data); end function playButton(src,~) fig = ancestor(src,'figure'); data = guidata(fig); if isempty(data.recordedSignal) set(data.statusText,'String','MAGNETOFON: nejprve nahrajte sekvenci'); return end set(data.statusText,'String','MAGNETOFON: ▶ PLAY'); sound(data.recordedSignal,data.Fe); end function saveButton(src,~) fig = ancestor(src,'figure'); data = guidata(fig); if isempty(data.recordedSignal) set(data.statusText,'String','MAGNETOFON: není co uložit'); return end audiowrite('SYN_LAB_recording.wav',data.recordedSignal,data.Fe); set(data.statusText,'String','MAGNETOFON: uloženo SYN_LAB_recording.wav'); end