1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef LOG_TAG
16 #define LOG_TAG "AudioBlendmodeTest"
17 #endif
18
19 #include <cstdio>
20 #include <iostream>
21
22 #include "audio_renderer_log.h"
23 #include "audio_system_manager.h"
24 #include "pcm2wav.h"
25 #include "audio_renderer.h"
26
27 using namespace OHOS::AudioStandard;
28 using namespace std;
29
30 namespace {
31 constexpr uint8_t SLEEP_TIME = 2;
32 constexpr int32_t SAMPLE_FORMAT_U8 = 8;
33 constexpr int32_t SAMPLE_FORMAT_S16LE = 16;
34 constexpr int32_t SAMPLE_FORMAT_S24LE = 24;
35 constexpr int32_t SAMPLE_FORMAT_S32LE = 32;
36 } // namespace
37
GetSampleFormat(int32_t wavSampleFormat)38 static AudioSampleFormat GetSampleFormat(int32_t wavSampleFormat)
39 {
40 switch (wavSampleFormat) {
41 case SAMPLE_FORMAT_U8:
42 return AudioSampleFormat::SAMPLE_U8;
43 case SAMPLE_FORMAT_S16LE:
44 return AudioSampleFormat::SAMPLE_S16LE;
45 case SAMPLE_FORMAT_S24LE:
46 return AudioSampleFormat::SAMPLE_S24LE;
47 case SAMPLE_FORMAT_S32LE:
48 return AudioSampleFormat::SAMPLE_S32LE;
49 default:
50 return AudioSampleFormat::INVALID_WIDTH;
51 }
52 }
53
CreateAudioRenderer(wav_hdr & wavHeader)54 static unique_ptr<AudioRenderer> CreateAudioRenderer(wav_hdr &wavHeader)
55 {
56 AudioRendererOptions rendererOptions;
57 rendererOptions.streamInfo.samplingRate = AudioSamplingRate::SAMPLE_RATE_44100;
58 rendererOptions.streamInfo.encoding = AudioEncodingType::ENCODING_PCM;
59 rendererOptions.streamInfo.format = GetSampleFormat(wavHeader.bitsPerSample);
60 rendererOptions.streamInfo.channels = (AudioChannel)wavHeader.NumOfChan;
61 rendererOptions.rendererInfo.contentType = ContentType::CONTENT_TYPE_MUSIC;
62 rendererOptions.rendererInfo.streamUsage = StreamUsage::STREAM_USAGE_MEDIA;
63 rendererOptions.rendererInfo.rendererFlags = 0;
64 return AudioRenderer::Create(rendererOptions);
65 }
66
StartRendererPlayback(char * inputPath,int mode)67 static int32_t StartRendererPlayback(char *inputPath, int mode)
68 {
69 AUDIO_INFO_LOG("================PLAYBACK STARTED==================");
70 wav_hdr wavHeader;
71 size_t headerSize = sizeof(wav_hdr);
72 char path[PATH_MAX + 1] = { 0x00 };
73 if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
74 AUDIO_ERR_LOG("Invalid path");
75 return AUDIO_ERR;
76 }
77 AUDIO_INFO_LOG("path = %{public}s mode = %{public}d", path, mode);
78 FILE* wavFile = fopen(path, "rb");
79 if (wavFile == nullptr) {
80 AUDIO_ERR_LOG("Unable to open wave file");
81 return AUDIO_ERR;
82 }
83
84 (void)fread(&wavHeader, 1, headerSize, wavFile);
85
86 unique_ptr<AudioRenderer> audioRenderer = CreateAudioRenderer(wavHeader);
87 audioRenderer->SetChannelBlendMode((ChannelBlendMode)mode);
88 audioRenderer->Start();
89
90 size_t bufferLen;
91 audioRenderer->GetBufferSize(bufferLen);
92
93 uint8_t *buffer = (uint8_t *) malloc(bufferLen);
94
95 size_t minBytes = 4;
96
97 while (!feof(wavFile)) {
98 size_t bytesRead = fread(buffer, 1, bufferLen, wavFile);
99 int32_t bytesWritten = 0;
100 while ((static_cast<size_t>(bytesWritten) < bytesRead) &&
101 ((static_cast<size_t>(bytesRead) - bytesWritten) > minBytes)) {
102 bytesWritten += audioRenderer->Write(buffer + static_cast<size_t>(bytesWritten),
103 bytesRead - static_cast<size_t>(bytesWritten));
104 if (bytesWritten < 0) {
105 break;
106 }
107 }
108 }
109
110 audioRenderer->Drain();
111 audioRenderer->Stop();
112 audioRenderer->Release();
113
114 free(buffer);
115 fclose(wavFile);
116 sleep(SLEEP_TIME);
117 AUDIO_INFO_LOG("================PLAYBACK OVER==================");
118 return 0;
119 }
120
PrintUsage()121 static void PrintUsage()
122 {
123 cout << "[Audio BlendMode Test App]" << endl << endl;
124 cout << "Supported Functionalities:" << endl;
125 cout << " a) Plays an input audio file with blend mode"<< endl;
126 cout << "================================Usage=======================================" << endl << endl;
127 cout << "-p\n\tPlays an input audio file with blend mode" << endl;
128 cout << "\tUsage : ./audio_blendmode_test -p <audio file path> <blendmode>" << endl;
129 cout << "\tExample : ./audio_blendmode_test -p /data/test.wav 1" << endl << endl;
130 }
131
main(int argc,char * argv[])132 int main(int argc, char* argv[])
133 {
134 int c;
135 opterr = 0;
136 while ((c = getopt(argc, argv, "a:c:p:r:h")) != AUDIO_INVALID_PARAM) {
137 switch (c) {
138 case 'p':
139 StartRendererPlayback(optarg, atoi(argv[optind]));
140 break;
141 case 'h':
142 PrintUsage();
143 break;
144 default:
145 cout << "Unsupported option. Exiting!!!" << endl;
146 exit(0);
147 break;
148 }
149 }
150
151 return 0;
152 }
153