wav_parser.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "wav_parser.h"
  2. #define TAG "WavParser"
  3. const char* format_text(FormatTag tag) {
  4. switch(tag) {
  5. case FormatTagPCM:
  6. return "PCM";
  7. case FormatTagIEEE_FLOAT:
  8. return "IEEE FLOAT";
  9. default:
  10. return "Unknown";
  11. }
  12. };
  13. struct WavParser {
  14. WavHeaderChunk header;
  15. WavFormatChunk format;
  16. WavDataChunk data;
  17. size_t wav_data_start;
  18. size_t wav_data_end;
  19. };
  20. WavParser* wav_parser_alloc() {
  21. return malloc(sizeof(WavParser));
  22. }
  23. void wav_parser_free(WavParser* parser) {
  24. free(parser);
  25. }
  26. bool wav_parser_parse(WavParser* parser, Stream* stream, WavPlayerApp* app) {
  27. stream_read(stream, (uint8_t*)&parser->header, sizeof(WavHeaderChunk));
  28. stream_read(stream, (uint8_t*)&parser->format, sizeof(WavFormatChunk));
  29. stream_read(stream, (uint8_t*)&parser->data, sizeof(WavDataChunk));
  30. char segment_name[5];
  31. if(memcmp(parser->header.riff, "RIFF", 4) != 0) {
  32. strlcpy(segment_name, (char*)&parser->header.riff, sizeof(segment_name));
  33. FURI_LOG_E(TAG, "WAV: wrong RIFF header: '%s'", segment_name);
  34. return false;
  35. }
  36. if(memcmp(parser->header.wave, "WAVE", 4) != 0) {
  37. strlcpy(segment_name, (char*)&parser->header.wave, sizeof(segment_name));
  38. FURI_LOG_E(TAG, "WAV: wrong WAVE header: '%s'", segment_name);
  39. return false;
  40. }
  41. if(memcmp(parser->format.fmt, "fmt ", 4) != 0) {
  42. strlcpy(segment_name, (char*)&parser->format.fmt, sizeof(segment_name));
  43. FURI_LOG_E(TAG, "WAV: wrong fmt segment: '%s'", segment_name);
  44. return false;
  45. }
  46. if(parser->format.tag != FormatTagPCM) {
  47. FURI_LOG_E(
  48. TAG,
  49. "WAV: non-PCM format: %u (%s)",
  50. parser->format.tag,
  51. format_text(parser->format.tag));
  52. return false;
  53. }
  54. if(memcmp(parser->data.data, "LIST", 4) == 0) {
  55. FURI_LOG_D(TAG, "WAV: skipping LIST segment");
  56. stream_seek(stream, parser->data.size, StreamOffsetFromCurrent);
  57. stream_read(stream, (uint8_t*)&parser->data, sizeof(WavDataChunk));
  58. }
  59. if(memcmp(parser->data.data, "data", 4) != 0) {
  60. strlcpy(segment_name, (char*)&parser->data.data, sizeof(segment_name));
  61. FURI_LOG_E(TAG, "WAV: wrong data segment: '%s'", segment_name);
  62. return false;
  63. }
  64. FURI_LOG_I(
  65. TAG,
  66. "Format tag: %s, ch: %u, smplrate: %lu, bps: %lu, bits: %u",
  67. format_text(parser->format.tag),
  68. parser->format.channels,
  69. parser->format.sample_rate,
  70. parser->format.byte_per_sec,
  71. parser->format.bits_per_sample);
  72. app->sample_rate = parser->format.sample_rate;
  73. app->num_channels = parser->format.channels;
  74. app->bits_per_sample = parser->format.bits_per_sample;
  75. parser->wav_data_start = stream_tell(stream);
  76. parser->wav_data_end = parser->wav_data_start + parser->data.size;
  77. FURI_LOG_I(TAG, "data: %u - %u", parser->wav_data_start, parser->wav_data_end);
  78. return true;
  79. }
  80. size_t wav_parser_get_data_start(WavParser* parser) {
  81. return parser->wav_data_start;
  82. }
  83. size_t wav_parser_get_data_end(WavParser* parser) {
  84. return parser->wav_data_end;
  85. }
  86. size_t wav_parser_get_data_len(WavParser* parser) {
  87. return parser->wav_data_end - parser->wav_data_start;
  88. }