使用MATLAB GUI的乐谱

时间:2013-11-13 12:55:12

标签: matlab user-interface

我正在制作一个自动转录钢琴音乐(单声道)的项目。我想创建一个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行)。

1 个答案:

答案 0 :(得分:3)

我的第一次吵架

我为音乐GUI制作了一个存根,如下所示。

到目前为止的结果:

Grand staff

我采取的方法如下:

  1. 上网并找到(免版税)高音谱号,低音谱号和大括号的SVG图像。
  2. 遗憾的是,MATLAB不支持矢量图形。因此,将这些SVG转换为合理的高分辨率PNG。
  3. 将这些图像重新缩放并放置在MATLAB图中。
  4. 在下面包含我的存根,它显示了我将采取的整体策略。基本上,我会对所有笔记,休止符,锐利等使用相同的方法, fixed 的符号。查找/创建符号的图像,将其加载到MATLAB中,并在需要的地方和时间缩放/显示它。

    当然,你必须有点创意。例如,您不需要128 th -rest的图像;只需复制8 th 休息3次,并稍微偏移每个副本。另一个例子:在头部和尾部分开单个8 th 音符的图像。它的头部等于四分音符,它的尾部仅在绘制了同一个和弦的最后一个音符后绘制。

    对于绘制非固定符号(想想连线符号,连接≤8 th 注释组等的线条),你必须做出决定:< / p>

    1. 手动绘制。您必须具有linepatch等所有内置绘图功能的创意。可能非常耗时。
    2. 使用图片,并与imtransform和朋友一起发挥创意。好处是结果可能看起来更好,并且它可能会消耗更少的时间。缺点是这些是图像处理工具箱的一部分,并非所有用户都可以访问。
    3. 真的最好:检测用户是否有图像处理工具箱(使用ver('images'))。如果是,请使用选项2.如果否,请使用选项1.
    4. 另一个选项

      另一种选择是使用专门的音乐字体。音乐字体将字符映射到音乐符号。好的字体是可矢量化的,这意味着它们可以任意大小缩放而不会降低质量。这消除了许多这些图像的需要。您需要担心的是将正确的字符映射到所需的符号以及角色的位置。

      但是,对于像和弦和非固定符号这样的东西,你仍然需要使用图像。

      The Stub

      但是现在,这是我使用的存根:

      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.pngFClef.pngbrace.png在与类定义相同的目录中: