我正在制作一个自动转录钢琴音乐(单声道)的项目。我想创建一个MATLAB GUI,可以显示转录音乐的乐谱。但是我不太确定如何在MATLAB GUI上设计Grand Staff。这是我第一次使用GUI,真的很喜欢一些帮助。 我遇到过这个链接,并希望有类似的东西,唯一的问题是我将加载一个.wav文件,而不是手动给出一个旋律。 http://www.pgea.unb.br/~mylene/PSMM/DSPFIRST/chapters/9specta/demos/musicgui/index.htm
我正在使用MATLAB R2011a软件。 Thanx提前:))
This is called the grand staff
我目前专注于只用谱号显示高音谱号(前5行)。
答案 0 :(得分:3)
我为音乐GUI制作了一个存根,如下所示。
到目前为止的结果:
我采取的方法如下:
在下面包含我的存根,它显示了我将采取的整体策略。基本上,我会对所有笔记,休止符,锐利等使用相同的方法, fixed 的符号。查找/创建符号的图像,将其加载到MATLAB中,并在需要的地方和时间缩放/显示它。
当然,你必须有点创意。例如,您不需要128 th -rest的图像;只需复制8 th 休息3次,并稍微偏移每个副本。另一个例子:在头部和尾部分开单个8 th 音符的图像。它的头部等于四分音符,它的尾部仅在绘制了同一个和弦的最后一个音符后绘制。
对于绘制非固定符号(想想连线符号,连接≤8 th 注释组等的线条),你必须做出决定:< / p>
line
,patch
等所有内置绘图功能的创意。可能非常耗时。imtransform
和朋友一起发挥创意。好处是结果可能看起来更好,并且它可能会消耗更少的时间。缺点是这些是图像处理工具箱的一部分,并非所有用户都可以访问。 ver('images')
)。如果是,请使用选项2.如果否,请使用选项1. 另一种选择是使用专门的音乐字体。音乐字体将字符映射到音乐符号。好的字体是可矢量化的,这意味着它们可以任意大小缩放而不会降低质量。这消除了许多这些图像的需要。您需要担心的是将正确的字符映射到所需的符号以及角色的位置。
但是,对于像和弦和非固定符号这样的东西,你仍然需要使用图像。
但是现在,这是我使用的存根:
classdef SheetMusicGui < handle
properties (Access = private)
f % Figure handle
h % Axes handle
% Coordinates of the box
topLineY = 0.8;
bottomLineY = 0.2;
leftLineX = 0.1;
maxX = 3;
end
methods
function obj = SheetMusicGui(varargin)
% Initialize figure and axis
obj.f = figure; clf, hold on
set(obj.f,...
'position', [400 400 900 300]);
obj.h = gca;
set(obj.h, ...
'box', 'on',...
'xtick',[], 'xticklabel',[],...
'ytick',[], 'yticklabel',[]);
% Draw the grande staff
obj.drawGrandeStaff(obj.h);
% Make sure all measurements work out
axis([0 3 0 1]);
end
end
methods (Access = private)
%% The Basics
function [h] = drawGrandeStaff(obj, h)
% First bar line
line([obj.leftLineX obj.leftLineX], [obj.bottomLineY obj.topLineY], 'color', 'k');
% Brace
img = imread('brace.png');
X = size(img,2); xExtent = 0.068;
Y = size(img,1); yExtent = xExtent/X*Y;
C = imagesc([0.01 0.01+xExtent],[0.8 0.8-yExtent],img, 'parent',obj.h);
uistack(C, 'bottom'); % At the bottom prevents transparency issues
% Treble staff
line(...
repmat([obj.leftLineX; obj.maxX],1,5), ...
repmat(linspace(obj.topLineY, obj.topLineY-0.15, 5), 2,1), 'color','k')
% Treble clef
obj.drawTrebleClef(obj.leftLineX+0.04, obj.topLineY+0.05);
% Bass staff
line(...
repmat([obj.leftLineX; obj.maxX],1,5),...
repmat(linspace(obj.bottomLineY, obj.bottomLineY+0.15, 5), 2,1), 'color','k')
% Bass clef
obj.drawBassClef(obj.leftLineX+0.04, obj.bottomLineY+0.155);
end
% Draw a G clef at location X,Y
function C = drawTrebleClef(obj, x, y)
persistent img
if isempty(img)
img = imread('GClef.png'); end
% Scale image
X = size(img,2); xExtent = 0.1;
Y = size(img,1); yExtent = xExtent/X*Y;
% Plage image
C = imagesc([x x+xExtent],[y y-yExtent],img, 'parent',obj.h);
uistack(C, 'bottom'); % At the bottom prevents transparency issues
end
% Draw an F clef at location X,Y
function C = drawBassClef(obj, x, y)
persistent img
if isempty(img)
img = imread('FClef.png'); end
% Scale image
X = size(img,2); xExtent = 0.12;
Y = size(img,1); yExtent = xExtent/X*Y;
% Plage image
C = imagesc([x x+xExtent],[y y-yExtent],img, 'parent',obj.h);
uistack(C, 'bottom'); % At the bottom prevents transparency issues
end
function T = drawTime(obj, varargin)
% TODO
% NOTE: you had best use some pre-defined times, like common time,
% 2/2, 3/4, 6/8, etc. It looks much nicer. Only use text() when a
% non-common time is encountered.
end
function K = drawKey(obj, varargin)
% TODO
% NOTE: use sharp/flat below
end
%% Sharps, flats
function T = drawSharp(obj, varargin)
% TODO
end
function T = drawDoubleSharp(obj, varargin)
% TODO
end
function T = drawFlat(obj, varargin)
% TODO
end
function T = drawDoubleFlat(obj, varargin)
% TODO
end
function T = drawNatural(obj, varargin)
% TODO
end
%% Bars
function B = drawBar(obj, varargin)
% TODO
end
function R = drawBeginRepeat(obj, varargin)
% TODO
end
function R = drawEndRepeat(obj, varargin)
% TODO
end
%% Pedalling
function P = drawBeginPedal(obj, varargin)
% TODO
end
function P = drawEndPedal(obj, varargin)
% TODO
end
%% Slurs & lines
function S = drawSlur(obj, varargin)
% TODO
% NOTE: You'll have to do this one by hand
end
function P = drawGlissando(obj, varargin)
% TODO
end
%% Multi-measure rest
function R = drawMultiMeasureRest(obj, varargin)
% TODO
end
%% Whole note/rest
function N = drawWholeNote(obj, pitch, varargin)
% TODO
% Possibly transform note
N = obj.transformNote(N, varargin{:});
end
function R = drawWholeRest(obj, varargin)
% TODO
% Possibly transform rest
N = obj.transformNote(N, varargin{:});
end
%% Half note/rest
function N = drawHalfNote(obj, varargin)
% TODO
% Possibly transform note
N = obj.transformNote(N, varargin{:});
end
function R = drawHalfRest(obj, varargin)
% TODO
% Possibly transform rest
N = obj.transformNote(N, varargin{:});
end
%% Quarter note/rest
function N = drawQuarterNote(obj, varargin)
% TODO
% Possibly transform note
N = obj.transformNote(N, varargin{:});
end
function R = drawQuarterRest(obj, varargin)
% TODO
% Possibly transform rest
N = obj.transformNote(N, varargin{:});
end
%% 8th, 16th, 32nd, 64th, ...
function N = drawSingleShortNote(obj, type, varargin)
% TODO
% NOTE: all short notes have a different number of tails. Just store
% the tail as a separate figure, and copy however many times needed.
% Use the quarter note for the head.
% Possibly transform rest
N = obj.transformNote(N, varargin{:});
end
function R = drawShortRest(obj, type, varargin)
% TODO
% NOTE: all short rests are just copies of the eighth rest, so you can
% juse load one image and copy the desired number of times.
% Possibly transform rest
N = obj.transformNote(N, varargin{:});
end
function N = drawShortNoteGroup(obj, types, varargin)
% TODO
% NOTE: Use the quarter note for all the heads. Draw however many
% lines (with "line" command) where needed. Top line should be
% "fatter"; you can do this by adjusting the "linewidth" property
% Possibly transform one or more members of the group
N = obj.transformNote(N, varargin{:});
end
%% Note/Rest transformations
% (dots, accents, inversion, decoration, etc.)
function N = transformNote(obj, N, varargin)
parameters = varargin(1:2:end);
values = varargin(2:2:end);
if mod(nargin,2)~=0 || ...
~all(cellfun('isclass', parameters), 'char') || ...
~all(cellfun('isclass', values), 'char')
error('transformNotes:no_pv_pairs',...
'Transforming notes is done by all-text parameter/value pairs.');
end
if numel(parameters)==0
return; end
for ii = 1:numel(parameters)
parameter = lower(parameters{ii});
value = lower(values{ii});
switch parameter
% Note may be flipped
case 'orientation'
switch value
case {'upright' 'normal'}
% No action
case {'flip', 'flipped', 'upside down'}
N = flipdim(N,1);
otherwise
% error
end
% Duration of note may be extended
case {'extend' 'extension'}
switch value
case {'single' 'dot'}
case {'double' 'dotdot' 'dot dot' 'ddot'}
case {'triple' 'dotdotdot' 'dot dot dot' 'dddot'}
otherwise
% error
end
% Note may be accented
case {'accent' 'accented'}
switch value
case 'portato'
case 'staccato'
case 'staccatissimo'
case 'legato'
case 'marcato'
case 'marcatissimo'
case 'tenuto'
otherwise
% error
end
% Note may be decorated
case {'decoration' 'decorated'}
switch value
case {'thril' 'thriller'}
case {'pralthril' 'pralthriller' 'praller'}
case 'mordent'
case 'arpeggio'
case 'gruppetto'
case 'glissando'
case 'portamento'
case 'schleifer'
case {'grace note' 'appoggiatura'}
case {'striped grace note' 'acciaccatura'}
otherwise
% error
end
otherwise
warning('transformNotes:unsupported_parameter',...
'Unknown parameter: ''%s''. Ignoring...', parameter);
end
end
end % transformNote
end % Private methods
end % Class definition
并且,只是这样你就可以按原样运行它,将这些图像保存为GClef.png
,FClef.png
和brace.png
在与类定义相同的目录中: