1 #include "widget.h"
2 #include "ui_widget.h"
3
4 #include <QFileDialog>
5 #include <QTimer>
6 #include <QTime>
7 #include <QDebug>
8 #include <QCoreApplication>
9
Widget(QWidget * parent)10 Widget::Widget(QWidget *parent)
11 : IWidget(parent)
12 , ui(new Ui::Widget)
13 {
14 ui->setupUi(this);
15 ui->lcdNumber->setDigitCount(8);
16
17 ui->dirEdit->installEventFilter(this);
18
19 capturing = false;
20 record_init();
21
22 connect(&timer, &QTimer::timeout, this, [=](){
23 QTime m_time;
24 m_time.setHMS(0, 0, 0, 0);
25 QString timestr = m_time.addSecs(startTime.secsTo(QDateTime::currentDateTime())).toString("hh:mm:ss");
26 ui->lcdNumber->display(timestr);
27 });
28 }
29
~Widget()30 Widget::~Widget()
31 {
32 delete ui;
33 }
34
id()35 QString Widget::id()
36 {
37 return "audiorecorder";
38 }
39
record_init()40 void Widget::record_init()
41 {
42 card = 3;
43 device = 0;
44 ahub_card = 1;
45 ahub_device = 1;
46
47 channels = 2;
48 rate = 44100;
49 bits = 16;
50 period_size = 1024;
51 period_count = 4;
52 format = PCM_FORMAT_S16_LE;
53
54 header.riff_id = ID_RIFF;
55 header.riff_sz = 0;
56 header.riff_fmt = ID_WAVE;
57 header.fmt_id = ID_FMT;
58 header.fmt_sz = 16;
59 header.audio_format = FORMAT_PCM;
60 header.num_channels = channels;
61 header.sample_rate = rate;
62
63 header.bits_per_sample = pcm_format_to_bits(format);
64 header.byte_rate = (header.bits_per_sample / 8) * channels * rate;
65 header.block_align = channels * (header.bits_per_sample / 8);
66 header.data_id = ID_DATA;
67 }
68
69
capture_sample()70 unsigned int Widget::capture_sample()
71 {
72 struct pcm_config config;
73 struct pcm *pcm;
74 struct pcm *ahub_pcm;
75 char *buffer;
76 unsigned int size;
77 unsigned int frames = 0;
78 unsigned int bytes_read = 0;
79
80 memset(&config, 0, sizeof(config));
81 config.channels = channels;
82 config.rate = rate;
83 config.period_size = period_size;
84 config.period_count = period_count;
85 config.format = format;
86 config.start_threshold = 0;
87 config.stop_threshold = period_count * period_size;
88 config.silence_threshold = 0;
89
90 pcm = pcm_open(card, device, PCM_IN, &config);
91 if (!pcm || !pcm_is_ready(pcm)) {
92 fprintf(stderr, "Unable to open PCM device (%s)\n",
93 pcm_get_error(pcm));
94 return -1;
95 }
96 pcm_start(pcm);
97
98 ahub_pcm = pcm_open(ahub_card, ahub_device, PCM_IN, &config);
99 if (!ahub_pcm || !pcm_is_ready(ahub_pcm)) {
100 fprintf(stderr, "Unable to open AHub device %d (%s)\n",
101 ahub_device, pcm_get_error(ahub_pcm));
102 pcm_close(pcm);
103 return -1;
104 }
105
106 size = pcm_frames_to_bytes(ahub_pcm, pcm_get_buffer_size(ahub_pcm));
107 buffer = (char *)malloc(size);
108 if (!buffer) {
109 fprintf(stderr, "Unable to allocate %d bytes\n", size);
110 free(buffer);
111 pcm_close(ahub_pcm);
112 pcm_close(pcm);
113 return -1;
114 }
115
116 printf("Capturing sample: %u ch, %u hz, %u bit, malloc buffer:%d\n",
117 channels, rate, pcm_format_to_bits(format), size);
118
119 while (capturing && !pcm_read(ahub_pcm, buffer, size)) {
120
121 if (fwrite(buffer, 1, size, file) != size) {
122 fprintf(stderr,"Error capturing sample\n");
123 break;
124 }
125 bytes_read += size;
126 QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
127 }
128
129 frames = pcm_bytes_to_frames(ahub_pcm, bytes_read);
130
131 free(buffer);
132 pcm_close(ahub_pcm);
133 pcm_close(pcm);
134
135 return frames;
136 }
137
138
on_pushButton_clicked()139 void Widget::on_pushButton_clicked()
140 {
141 QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"),
142 "/",
143 QFileDialog::ShowDirsOnly
144 | QFileDialog::DontResolveSymlinks);
145 if (!dir.isEmpty())
146 ui->dirEdit->setText(dir + "/record.wav");
147 }
148
on_startBtn_clicked()149 void Widget::on_startBtn_clicked()
150 {
151 file = fopen(ui->dirEdit->text().toLocal8Bit().data(), "wb");
152 if (!file) {
153 qDebug()<<ui->dirEdit->text()<<" open failed";
154 return;
155 }
156
157 ui->startBtn->setEnabled(false);
158 capturing = true;
159
160 /* leave enough room for header */
161 fseek(file, sizeof(struct wav_header), SEEK_SET);
162
163 startTime = QDateTime::currentDateTime();
164 timer.start(10);
165
166 int frames = capture_sample();
167
168 /* write header now all information is known */
169 header.data_sz = frames * header.block_align;
170 header.riff_sz = header.data_sz + sizeof(header) - 8;
171 fseek(file, 0, SEEK_SET);
172 fwrite(&header, sizeof(struct wav_header), 1, file);
173 fclose(file);
174 }
175
on_stopBtn_clicked()176 void Widget::on_stopBtn_clicked()
177 {
178 timer.stop();
179 capturing = false;
180 ui->startBtn->setEnabled(true);
181 }
182