/io/wavelet.d

http://github.com/wilkie/djehuty · D · 182 lines · 103 code · 52 blank · 27 comment · 10 complexity · f3f94dd2c666b1c97eadd54e404e7ae7 MD5 · raw file

  1. module io.wavelet;
  2. import core.stream;
  3. import core.string;
  4. import core.definitions;
  5. import core.time;
  6. import io.audio;
  7. import io.console;
  8. import math.common;
  9. import math.vector;
  10. enum Interpolate {
  11. Zeroth,
  12. Linear,
  13. }
  14. // Section: Core/Streams
  15. // Description: This class represents an audio buffer. You can do simple transforms on the audio data using the provided methods. It is essentially a Stream, and you can read and write to the buffer in the same fashion.
  16. class Wavelet : Stream {
  17. // Constructors //
  18. // Description: Will create a small buffer. This will presumedly be resized.
  19. this() {
  20. super(1);
  21. }
  22. // -- Methods -- //
  23. // Description: Will get the format of the audio information.
  24. // Returns: An AudioFormat struct containing useful information such as sample rate and average bytes per second.
  25. AudioFormat audioFormat() {
  26. return _fmt;
  27. }
  28. // Description: Will set the audio format of the buffer. Audio Codecs will set this automatically, but if the buffer format is otherwise unknown, it can be set using this function.
  29. // audFormat: An AudioFormat struct describing the contents of the buffer.
  30. void setAudioFormat(AudioFormat audFormat) {
  31. _fmt = audFormat;
  32. }
  33. // -- Computations -- //
  34. void upSample(Interpolate interpType) {
  35. }
  36. void downSample(Interpolate interpType) {
  37. }
  38. void pitchBend() {
  39. }
  40. void pitchShift() {
  41. }
  42. // Description: This function will shorten the wavelet to a specified region.
  43. void crop(Time start) {
  44. // is this necessary?
  45. if (start > time() || start is null) {
  46. // error
  47. Console.put("error");
  48. return;
  49. }
  50. Time len = time() - start;
  51. int newLength;
  52. int newStartPos;
  53. ubyte olddata[] = _data;
  54. newLength = cast(int)((_fmt.averageBytesPerSecond / 1000) * (len.microseconds / 1000));
  55. newStartPos = cast(int)((_fmt.averageBytesPerSecond / 1000) * (start.microseconds / 1000));
  56. _data = new ubyte[newLength];
  57. _data[0..$] = olddata[newStartPos..(newStartPos + newLength)];
  58. _length = newLength;
  59. _capacity = newLength;
  60. }
  61. // Description: This function will shorten the wavelet to a specified region.
  62. void crop(Time start, Time len) {
  63. // is this necessary?
  64. if (start > time()) {
  65. // error
  66. Console.put("error");
  67. return;
  68. }
  69. if (len + start > time()) {
  70. // error
  71. Console.put("error");
  72. return;
  73. }
  74. int newLength;
  75. int newStartPos;
  76. ubyte olddata[] = _data;
  77. newLength = cast(int)((_fmt.averageBytesPerSecond / 1000) * (len.microseconds / 1000));
  78. newStartPos = cast(int)((_fmt.averageBytesPerSecond / 1000) * (start.microseconds / 1000));
  79. _data = new ubyte[newLength];
  80. _data[0..$] = olddata[newStartPos..(newStartPos + newLength)];
  81. _length = newLength;
  82. _capacity = newLength;
  83. }
  84. // Description: This function will return the amount of time this block represents
  85. Time time() {
  86. Time tme = new Time();
  87. // the amount of bytes / amount of bytes per second = seconds
  88. if (_fmt.averageBytesPerSecond == 0) {
  89. return tme;
  90. }
  91. float amtSeconds = (cast(float)length() / cast(float)_fmt.averageBytesPerSecond);
  92. tme.microseconds = cast(long)(amtSeconds * 1000000);
  93. return tme;
  94. }
  95. cdouble[] fourier(int samples = 512, uint skipSamples = 0) {
  96. if ((samples + skipSamples) * _fmt.numChannels > (this.length / 2)) {
  97. samples = cast(int)((this.length / 2 / _fmt.numChannels) - skipSamples);
  98. }
  99. if (samples < 0) {
  100. return [];
  101. }
  102. uint rem = 1;
  103. // floor samples to nearest power of 2
  104. while(samples > 0) {
  105. samples >>= 1;
  106. rem <<= 1;
  107. }
  108. rem >>= 1;
  109. cdouble[] ret = new cdouble[rem];
  110. // I'll just average the channels, if possible
  111. short* ptr = cast(short*)&_data[0];
  112. size_t idx = skipSamples * _fmt.numChannels;
  113. for(size_t sample = 0; sample < rem; sample++, idx += _fmt.numChannels) {
  114. cdouble data = 0.0 + 0.0i;
  115. for(size_t channel = 0; channel < _fmt.numChannels; channel++) {
  116. data += (cast(cdouble)ptr[idx + channel] / cast(cdouble)short.max);
  117. }
  118. ret[sample] = data / _fmt.numChannels;
  119. }
  120. return ret.fft();
  121. }
  122. private:
  123. // Reference to the Audio Format
  124. // of this collection of samples
  125. // This is used for playback and is
  126. // also used for calculations and
  127. // transformations
  128. AudioFormat _fmt;
  129. }
  130. //alias WaveletImpl!(StreamAccess.AllAccess) Wavelet;