SHARE
TWEET

Untitled

a guest Sep 20th, 2019 80 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. K = 100001;
  20. %Smoothness factor to be used later. This is the amount of data points
  21. %around a data point over which the average is calculated.
  22.  
  23. [s,Fs] = audioread('klaatu.wav');
  24. %Read audio file and place it in array s
  25.  
  26. Output_Array = thatwayRMSConverter(s,K);
  27. %Normalize it and place the output in Output_Array
  28.  
  29. audiowrite('output.flac',Output_Array, Fs);
  30. %Write Output_Array to a file
  31.  
  32.  
  33. function arr_Output = thatwayRMSConverter(arr_A,K)
  34.  
  35. squaredData = arr_A .* arr_A;
  36. % Square the input data
  37. SummedData = smoothdata(squaredData, 'movmean', K);
  38. % We use the 'smoothdata' function supplied by matlab to find the average
  39. % ('movmean' flag) 'loudness' over a certain timeperiod (in this case the
  40. % timeperiod is K = 100 001 samples long). For every point in arr_B it
  41. % looks X values back and X values forward, adds these values together and
  42. % divides this by X+X+1 to get the average over that period, and places it
  43. % in arr_C. This is the 'Mean' step of RMS and will result in the squaredRMS
  44. % array.
  45.  
  46. % If K were to be too small, let's say K = 1, then later on when
  47. % normalizing the sound, the result for every data point would be exactly
  48. % the same, removing the variations needed for carrying the data (The
  49. % result would probably be a continuous single tone, if it results in
  50. % anything at all).
  51.  
  52. rootSummedData = arrayfun(@RootTaker,SummedData);
  53. % This takes the root of the squared RMS array.
  54.  
  55. global MaxValRMS;
  56. MaxValRMS = max(rootSummedData);
  57.  
  58. % We find the highest point of the RMS. We will use this to find the
  59. % average amplification that every datapoint will strive towards. See the
  60. % explanation at the amplitudeMod function for more info.
  61.  
  62. % The variable MaxValRms is declared global because matlab works in such a
  63. % way that any variable in any scope is NOT accesable in any other scope.
  64. % In this case, we're in the 'Base' scope, but any functions have their own
  65. % 'Function' scope, and cannot see any variables in the 'Base' scope.
  66. % Declaring the variable as global in both 'Base' and 'Function' allows for
  67. % sharing a single variable accross multiple scopes.
  68.  
  69. arr_AmpMod = arrayfun(@amplitudeMod,rootSummedData);
  70. % We make an array with values that are the INVERSE of the RMS. The loud
  71. % parts will have a low value, and the quit parts will have a high value.
  72.  
  73. arr_Normalized = arr_A .* arr_AmpMod;
  74. % We now multiply the original input signal with the inverse-RMS. Since the
  75. % quit parts have a high inverse-RMS value, multiplying them with the input
  76. % signal will increase the 'quit part' amplitude. Since the loud parts have
  77. % a low inverse-RMS value, multiplying the input with this inverse RMS
  78. % value results in a lower amplitude.
  79. % Basically, this is the part where we make the quit parts loud and the
  80. % loud parts quit, as to make them all approximately the same level.
  81.  
  82.  
  83. global MaxValInput;
  84. MaxValInput = max(arr_A);
  85. arr_Output = arrayfun(@removePeaks,arr_Normalized);
  86. % This part above is completely optional. After running the normalization
  87. % part above, I saw that there were some data spikes caused by the fact
  88. % that the RMS is the value over a certain period, but in this period could
  89. % be very high peaks that now also get amplified the same as its quiter
  90. % neighbour values. This results in an output with some spikes at some
  91. % parts, which could be unenjoyable. This part just removes the peaks.
  92.  
  93. %We return the arr_output which will then be written to a file.
  94.  
  95. %% The part below plots all the graph of every intermediate step.
  96.  
  97. figure(1);
  98. plot(arr_A);
  99. % "Representation of Input Data"
  100. figure(2);
  101. plot(squaredData);
  102. % "Squared input data"
  103. hold on
  104. plot(SummedData);
  105. % This is the RMS-Squared
  106. hold on
  107. plot(rootSummedData);
  108. % This is the root of the RMS-squared. This is the RMS.
  109.  
  110. figure(3);
  111. plot(arr_AmpMod);
  112. % "Inverse of RMS"
  113. figure(4);
  114. plot(arr_Normalized);
  115. % "Input data multiplied by the inverse amplitudes, normalized"
  116. figure(5);
  117. plot(arr_Output);
  118. % "Output array, without spikes"
  119.  
  120.  
  121. end
  122.  
  123.  
  124. %% Functions
  125.  
  126. function output = RootTaker(datapoint)
  127.     output = sqrt(datapoint);
  128. end
  129. % This returns the root of the data point.
  130.  
  131. function output = amplitudeMod(x)
  132.     global MaxValRMS;
  133.     output = (MaxValRMS/2) / x;
  134. end
  135. % As explained above, MaxValRMS is global to be accesable in this scope.
  136. % MaxValRms/2 is half the loudness of the loud parts, which should also be
  137. % about double the loudness of quiet parts. By dividing this by low (quiet)
  138. % value, it will return a high value (1 / 0.5 = 2), and by dividing the
  139. % MaxValRMS/2 by a high value, it will return a lower value (1 / 2 = 0.5).
  140.  
  141. % Basically this returns the amplification needed to get a datapoint to
  142. % the average loudness.
  143.  
  144. function output = removePeaks(x)
  145.     global MaxValInput;
  146.     if x > ((MaxValInput/3)*2)
  147.         output = ((MaxValInput/3)*2);
  148.     elseif x < ((-MaxValInput / 3) * 2)
  149.         output = ((-MaxValInput/3)*2);
  150.     else
  151.         output = x;
  152.     end
  153. end
  154. % This function checks if the data point is above 2/3rd of the original
  155. % 'loud' part (meaning it is a spike), and if that is the case it changes
  156. % its value to be 2/3rd of the original input loud part. This checks for
  157. % both positive and negative datapoints since sound in this case is an
  158. % 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