TTKMusicPlayer  3.7.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musicaudiorecordermodule.cpp
Go to the documentation of this file.
2 
3 static constexpr int OPEN_FILE_ERROR = -1;
4 static constexpr int SAVE_FILE_ERROR = -2;
5 static constexpr int WRITE_FILE_ERROR = -3;
6 static constexpr int REWRITE_FILE_ERROR = -4;
7 
8 struct WavHeader
9 {
10  char riffName[4];
11  ulong riffLength;
12  char wavName[4];
13  char fmtName[4];
14  ulong fmtLength;
15  ushort audioFormat;
16  ushort channleNumber;
17  ulong sampleRate;
20  ushort bitsPerSample;
21  char dataName[4];
22  ulong dataLength;
23 };
24 
25 
27  : QObject(parent),
28  m_inputVolume(0),
29  m_audioInputFile(nullptr),
30  m_audioOutputFile(nullptr)
31 {
32  m_file = new QFile(this);
33  m_file->setFileName(TTK_RECORD_FILE);
34 
35  m_formatFile.setChannelCount(1);
36  m_formatFile.setSampleSize(16);
37  m_formatFile.setSampleRate(8000);
38  m_formatFile.setSampleType(QAudioFormat::SignedInt);
39  m_formatFile.setByteOrder(QAudioFormat::LittleEndian);
40  m_formatFile.setCodec("audio/pcm");
41 
42  const QAudioDeviceInfo input_info(QAudioDeviceInfo::defaultInputDevice());
43  if(!input_info.isFormatSupported(m_formatFile))
44  {
45  TTK_WARN_STREAM("Input default format file not supported try to use nearest");
46  m_formatFile = input_info.nearestFormat(m_formatFile);
47  }
48 
49  const QAudioDeviceInfo output_info(QAudioDeviceInfo::defaultOutputDevice());
50  if(!output_info.isFormatSupported(m_formatFile))
51  {
52  TTK_WARN_STREAM("Output default format file not supported - trying to use nearest");
53  TTK_WARN_STREAM("Output no support input format file.");
54  }
55 
56  if(m_formatFile.sampleSize() != 16)
57  {
58  TTK_INFO_STREAM(QString("Audio device doesn't support 16 bit support %d bit samples, example cannot run %1").arg(m_formatFile.sampleSize()));
59  }
60 }
61 
63 {
64  QFile::remove(TTK_RECORD_FILE);
65  QFile::remove(TTK_RECORD_DATA_FILE);
66 
67  delete m_file;
68  delete m_audioInputFile;
69  delete m_audioOutputFile;
70 }
71 
72 int MusicAudioRecorderModule::addWavHeader(const char *fileName) const
73 {
74  WavHeader fileHeader;
75  fileHeader.riffName[0] = 'R';
76  fileHeader.riffName[1] = 'I';
77  fileHeader.riffName[2] = 'F';
78  fileHeader.riffName[3] = 'F';
79 
80  fileHeader.wavName[0] = 'W';
81  fileHeader.wavName[1] = 'A';
82  fileHeader.wavName[2] = 'V';
83  fileHeader.wavName[3] = 'E';
84 
85  fileHeader.fmtName[0] = 'f';
86  fileHeader.fmtName[1] = 'm';
87  fileHeader.fmtName[2] = 't';
88  fileHeader.fmtName[3] = 0x20;
89  fileHeader.fmtLength = 16;
90  fileHeader.audioFormat = 1;
91 
92  fileHeader.dataName[0] = 'd';
93  fileHeader.dataName[1] = 'a';
94  fileHeader.dataName[2] = 't';
95  fileHeader.dataName[3] = 'a';
96  fileHeader.bitsPerSample = 16;
97  fileHeader.bytesPerSample = 2;
98  fileHeader.sampleRate = 8000;
99  fileHeader.bytesPperSecond = 16000;
100  fileHeader.channleNumber = 1;
101 
102  int fileLen = 0;
103  const int headerSize = sizeof(fileHeader);
104 
105  FILE *input = nullptr;
106  FILE *output = nullptr;
107  if((input = fopen(qPrintable(m_file->fileName()), "rb")) == nullptr)
108  {
109  return OPEN_FILE_ERROR;
110  }
111 
112  if((output = fopen(qPrintable(fileName), "wb+")) == nullptr)
113  {
114  return SAVE_FILE_ERROR;
115  }
116 
117  if(fwrite(&fileHeader, 1, headerSize, output) != headerSize)
118  {
119  fclose(input);
120  fclose(output);
121  return WRITE_FILE_ERROR;
122  }
123 
124  while(!feof(input))
125  {
126  char readBuf[4096];
127  const int nRead = fread(readBuf, 1, 4096, input);
128  if(nRead > 0)
129  {
130  fwrite(readBuf, 1, nRead, output);
131  }
132 
133  fileLen += nRead;
134  }
135 
136  fseek(output, 0L, SEEK_SET);
137  fileHeader.riffLength = fileLen - 8 + headerSize;
138  fileHeader.dataLength = fileLen;
139 
140  if(fwrite(&fileHeader, 1, headerSize, output) != headerSize)
141  {
142  fclose(input);
143  fclose(output);
144  return REWRITE_FILE_ERROR;
145  }
146 
147  fclose(input);
148  fclose(output);
149 
150  return fileLen;
151 }
152 
154 {
156 #if TTK_QT_VERSION_CHECK(5,0,0)
157  if(m_audioInputFile)
158  {
159  m_audioInputFile->setVolume(volume);
160  }
161 #endif
162 }
163 
165 {
166  return m_inputVolume;
167 }
168 
170 {
171  m_file->setFileName(name);
172 }
173 
175 {
176  return m_file->fileName();
177 }
178 
180 {
181  if(!m_audioInputFile)
182  {
183  return true;
184  }
185 
186  return m_audioInputFile->error() != QAudio::NoError;
187 }
188 
190 {
191  if(!m_file->isOpen())
192  {
193  m_file->open(QIODevice::WriteOnly | QIODevice::Truncate);
194  m_audioInputFile = new QAudioInput(m_formatFile, this);
195  }
196 
197  if(m_audioInputFile->error() != QAudio::NoError)
198  {
199  TTK_ERROR_STREAM("Audio input open error");
200  return;
201  }
202 
203 #if TTK_QT_VERSION_CHECK(5,0,0)
204  m_audioInputFile->setVolume(m_inputVolume);
205 #endif
206  m_audioInputFile->start(m_file);
207 }
208 
210 {
211  if(m_audioInputFile)
212  {
213  m_audioInputFile->stop();
214  delete m_audioInputFile;
215  m_audioInputFile = nullptr;
216  }
217 
219  {
220  m_audioOutputFile->stop();
221  delete m_audioOutputFile;
222  m_audioOutputFile = nullptr;
223  }
224 
225  m_file->close();
226 }
int addWavHeader(const char *fileName) const
void setFileName(const QString &name)
static constexpr int REWRITE_FILE_ERROR
#define qPrintable(s)
Definition: ttkqtglobal.h:36
#define TTK_WARN_STREAM(msg)
Definition: ttklogger.h:68
const char * name
Definition: http_parser.c:458
#define TTK_RECORD_DATA_FILE
#define TTK_INFO_STREAM(msg)
Definition: ttklogger.h:67
#define TTK_RECORD_FILE
static constexpr int WRITE_FILE_ERROR
#define SEEK_SET
Definition: zip.c:88
static constexpr int OPEN_FILE_ERROR
static constexpr int SAVE_FILE_ERROR
MusicAudioRecorderModule(QObject *parent=nullptr)
#define TTK_ERROR_STREAM(msg)
Definition: ttklogger.h:69