Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

82 řádky
1.8KB

  1. package recorder
  2. import (
  3. "encoding/binary"
  4. "os"
  5. )
  6. func writeWAV(path string, samples []float32, sampleRate int, channels int) error {
  7. f, err := os.Create(path)
  8. if err != nil {
  9. return err
  10. }
  11. defer f.Close()
  12. if channels <= 0 {
  13. channels = 1
  14. }
  15. // 16-bit PCM
  16. dataSize := uint32(len(samples) * 2)
  17. // RIFF header
  18. if _, err := f.Write([]byte("RIFF")); err != nil {
  19. return err
  20. }
  21. if err := binary.Write(f, binary.LittleEndian, uint32(36)+dataSize); err != nil {
  22. return err
  23. }
  24. if _, err := f.Write([]byte("WAVE")); err != nil {
  25. return err
  26. }
  27. // fmt chunk
  28. if _, err := f.Write([]byte("fmt ")); err != nil {
  29. return err
  30. }
  31. if err := binary.Write(f, binary.LittleEndian, uint32(16)); err != nil {
  32. return err
  33. }
  34. if err := binary.Write(f, binary.LittleEndian, uint16(1)); err != nil { // PCM
  35. return err
  36. }
  37. if err := binary.Write(f, binary.LittleEndian, uint16(channels)); err != nil {
  38. return err
  39. }
  40. if err := binary.Write(f, binary.LittleEndian, uint32(sampleRate)); err != nil {
  41. return err
  42. }
  43. byteRate := uint32(sampleRate * channels * 2)
  44. if err := binary.Write(f, binary.LittleEndian, byteRate); err != nil {
  45. return err
  46. }
  47. if err := binary.Write(f, binary.LittleEndian, uint16(channels*2)); err != nil {
  48. return err
  49. }
  50. if err := binary.Write(f, binary.LittleEndian, uint16(16)); err != nil { // bits
  51. return err
  52. }
  53. // data chunk
  54. if _, err := f.Write([]byte("data")); err != nil {
  55. return err
  56. }
  57. if err := binary.Write(f, binary.LittleEndian, dataSize); err != nil {
  58. return err
  59. }
  60. // samples
  61. for _, s := range samples {
  62. v := int16(clip(s * 32767))
  63. if err := binary.Write(f, binary.LittleEndian, v); err != nil {
  64. return err
  65. }
  66. }
  67. return nil
  68. }
  69. func clip(v float32) float32 {
  70. if v > 32767 {
  71. return 32767
  72. }
  73. if v < -32768 {
  74. return -32768
  75. }
  76. return v
  77. }