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