Advertisement
Guest User

Untitled

a guest
Sep 20th, 2019
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MatLab 6.03 KB | None | 0 0
  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.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement