about summary refs log tree commit diff
path: root/csrc/cbrr.c
blob: f1eb2bdff14d834a9101d372eb981df06bacf9ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

#include "cbrr.h"
#include <alsa/asoundlib.h>
#include <mpg123.h>
#include <stdio.h>
#include <stdlib.h>

#define PCM_DEVICE "default"

void brr_c(char *filename) {
  // Initialize the MPG123 library
  mpg123_init();
  mpg123_handle *mh = mpg123_new(NULL, NULL);
  if (mpg123_open(mh, filename) != MPG123_OK) {
    fprintf(stderr, "Error opening %s: %s\n", filename, mpg123_strerror(mh));
    return;
  }

  // Retrieve the format of the MP3 file
  long rate;
  int channels, encoding;
  if (mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK) {
    fprintf(stderr, "Error getting format: %s\n", mpg123_strerror(mh));
    return;
  }

  // Set the output format
  snd_pcm_t *pcm_handle;
  snd_pcm_hw_params_t *params;
  int pcm, dir;
  snd_pcm_uframes_t frames;
  char *buffer;
  int size;

  // Open the PCM device
  if (pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0) <
            0) {
    fprintf(stderr, "Error opening PCM device %s: %s\n", PCM_DEVICE,
            snd_strerror(pcm));
    return;
  }

  // Allocate hardware parameters object
  snd_pcm_hw_params_alloca(&params);
  snd_pcm_hw_params_any(pcm_handle, params);

  // Set the desired hardware parameters
  snd_pcm_hw_params_set_access(pcm_handle, params,
                               SND_PCM_ACCESS_RW_INTERLEAVED);
  snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE);
  snd_pcm_hw_params_set_channels(pcm_handle, params, channels);
  snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, &dir);

  // Write the parameters to the driver
  if (pcm = snd_pcm_hw_params(pcm_handle, params) < 0) {
    fprintf(stderr, "Error setting HW params: %s\n", snd_strerror(pcm));
    return;
  }

  // Use a buffer large enough to hold one period
  snd_pcm_hw_params_get_period_size(params, &frames, &dir);
  size = frames * channels * 2; // 2 bytes/sample, 2 channels
  buffer = (char *)malloc(size);

  // Decode and play the MP3 file
  size_t buffer_size = mpg123_outblock(mh);
  unsigned char *mpg123_buffer =
      (unsigned char *)malloc(buffer_size * sizeof(unsigned char));
  size_t done;
  int err;

  while ((err = mpg123_read(mh, mpg123_buffer, buffer_size, &done)) ==
         MPG123_OK) {
    snd_pcm_writei(pcm_handle, mpg123_buffer, done / 4);
  }

  // Clean up
  free(buffer);
  free(mpg123_buffer);
  snd_pcm_drain(pcm_handle);
  snd_pcm_close(pcm_handle);
  mpg123_close(mh);
  mpg123_delete(mh);
  mpg123_exit();

  return;
}