SHARE
TWEET

Untitled

a guest Sep 19th, 2019 160 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. % I have used some functions which are at the bottom of this file. I placed
  2. % comments in the function code as well, so in the 'main' code I will not
  3. % explain how the function works, just what it returns.
  4.  
  5. % I will give comments AFTER every line of code.
  6.  
  7. % I used the matlab-given function 'arrayfun' a few times. What this
  8. % function does is that it passes every point in a given array to a
  9. % function, and places the result in it's respective place in a new array.
  10. % It's syntax is "NewArray = arrayfun(@FunctionName, DataArray".
  11.  
  12. %% ****No for loops were used or harmed in the creation of this code.****
  13. %% Code Below
  14.  
  15. Fs = 44100;
  16. % Fs = The number of samples per second in which the input file is divided.
  17. % See lecture notes for how/why this method is used for digitalizing sound.
  18. % The industry standard is 44100.
  19.  
  20. [arr_A,Fs] = audioread('klaatu.wav');
  21. % Read the audio file and store it's data in array form.
  22.  
  23. arr_B = arrayfun(@absolute,arr_A);
  24. % We make the input data absolute (the root-square step of the RMS) so that
  25. % when we take the 'integral' of the data it doesn't result in 0.
  26.  
  27. K = 100001;
  28. arr_C = smoothdata(arr_B, 'movmean', K);
  29. % We use the 'smoothdata' function supplied by matlab to find the average
  30. % ('movmean' flag) 'loudness' over a certain timeperiod (in this case the
  31. % timeperiod is K = 100 001 samples long). For every point in arr_B it
  32. % looks X values back and X values forward, adds these values together and
  33. % divides this by X+X+1 to get the average over that period, and places it
  34. % in arr_C. This is the 'Mean' step of RMS.
  35.  
  36. % If K were to be too small, let's say K = 1, then later on when
  37. % normalizing the sound, the result for every data point would be exactly
  38. % the same, removing the variations needed for carrying the data (The
  39. % result would probably be a continuous single tone, if it results in
  40. % anything at all).
  41.  
  42. global MaxValRMS;
  43. MaxValRMS = max(arr_C);
  44. % We find the highest point of the RMS. We will use this to find the
  45. % average amplification that every datapoint will strive towards. See the
  46. % explanation at the amplitudeMod function for more info.
  47.  
  48. % The variable MaxValRms is declared global because matlab works in such a
  49. % way that any variable in any scope is NOT accesable in any other scope.
  50. % In this case, we're in the 'Base' scope, but any functions have their own
  51. % 'Function' scope, and cannot see any variables in the 'Base' scope.
  52. % Declaring the variable as global in both 'Base' and 'Function' allows for
  53. % sharing a single variable accross multiple scopes.
  54.  
  55. arr_AmpMod = arrayfun(@amplitudeMod,arr_C);
  56. % We make an array with values that are the INVERSE of the RMS. The loud
  57. % parts will have a low value, and the quit parts will have a high value.
  58.  
  59. arr_Normalized = arr_A .* arr_AmpMod;
  60. % We now multiply the original input signal with the inverse-RMS. Since the
  61. % quit parts have a high inverse-RMS value, multiplying them with the input
  62. % signal will increase the 'quit part' amplitude. Since the loud parts have
  63. % a low inverse-RMS value, multiplying the input with this inverse RMS
  64. % value results in a lower amplitude.
  65. % Basically, this is the part where we make the quit parts loud and the
  66. % loud parts quit, as to make them all approximately the same level.
  67.  
  68. global MaxValInput;
  69. MaxValInput = max(arr_B);
  70. arr_Output = arrayfun(@removePeaks,arr_Normalized);
  71. % This part above is completely optional. After running the normalization
  72. % part above, I saw that there were some data spikes caused by the fact
  73. % that the RMS is the value over a certain period, but in this period could
  74. % be very high peaks that now also get amplified the same as its quiter
  75. % neighbour values. This results in an output with some spikes at some
  76. % parts, which could be unenjoyable. This part just removes the peaks.
  77.  
  78. audiowrite('output.flac',arr_Output,Fs);
  79. % Write the final output in a sound file to be able to listen to the
  80. % result.
  81.  
  82. %% The part below plots all the graph of every intermediate step.
  83.  
  84. figure(1);
  85. plot(arr_A);
  86. % "Representation of Input Data"
  87. figure(2);
  88. plot(arr_B);
  89. % "Absolute-ed input data"
  90. hold on
  91. plot(arr_C);
  92. % RMS of absolute'd input array, overlayed on the absolute'd array to show
  93. % the level of RMS at any point in time, and easily visually compare to the
  94. % input data.
  95. figure(3);
  96. plot(arr_AmpMod);
  97. % "Inverse of RMS"
  98. figure(4);
  99. plot(arr_Normalized);
  100. % "Input data multiplied by the inverse amplitudes, normalized"
  101. figure(5);
  102. plot(arr_Output);
  103. % "Output array, without spikes"
  104.  
  105. %% Functions
  106. function output = absolute(x)
  107.     output = sqrt(x^2);
  108. end
  109. % Takes the input value, squares it and takes the root of this new value.
  110. % This is now the absolute value of the original value.
  111.  
  112. function output = amplitudeMod(x)
  113.     global MaxValRMS;
  114.     output = (MaxValRMS/2) / x;
  115. end
  116. % As explained above, MaxValRMS is global to be accesable in this scope.
  117. % MaxValRms/2 is half the loudness of the loud parts, which should also be
  118. % about double the loudness of quit parts. By dividing this by low (quit)
  119. % value, it will return a high value (1 / 0.5 = 2), and by dividing the
  120. % MaxValRMS/2 by a high value, it will return a lower value (1 / 2 = 0.5).
  121.  
  122. % Basically this returns the amplification needed to get a datapoint to
  123. % the average loudness.
  124.  
  125. function output = removePeaks(x)
  126.     global MaxValInput;
  127.     if x > ((MaxValInput/3)*2)
  128.         output = ((MaxValInput/3)*2);
  129.     elseif x < ((-MaxValInput / 3) * 2)
  130.         output = ((-MaxValInput/3)*2);
  131.     else
  132.         output = x;
  133.     end
  134. end
  135. % This function checks if the data point is above 2/3rd of the original
  136. % 'loud' part (meaning it is a spike), and if that is the case it changes
  137. % its value to be 2/3rd of the original input loud part. This checks for
  138. % both positive and negative datapoints since sound in this case is an
  139. % osscilation around zero.
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top