1 /*
2 * Copyright (c) 2021-2022 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 #include <cstdio>
16 #include <iostream>
17
18 #include "audio_stream.h"
19 #include "audio_system_manager.h"
20 #include "audio_log.h"
21 #include "pcm2wav.h"
22
23 using namespace OHOS::AudioStandard;
24
25 namespace {
26 constexpr uint8_t DEFAULT_FORMAT = SAMPLE_S16LE;
27 constexpr uint8_t DEFAULT_CHANNELS = 2;
28 constexpr int32_t ARGS_INDEX_TWO = 2;
29 constexpr int32_t ARGS_INDEX_THREE = 3;
30 } // namespace
31
32 class PlaybackTest : public AudioRendererCallbacks {
33 public:
OnSinkDeviceUpdatedCb() const34 void OnSinkDeviceUpdatedCb() const
35 {
36 AUDIO_INFO_LOG("My custom callback OnSinkDeviceUpdatedCb");
37 }
OnStreamStateChangeCb() const38 virtual void OnStreamStateChangeCb() const
39 {
40 AUDIO_INFO_LOG("My custom callback OnStreamStateChangeCb");
41 }
42
OnStreamBufferUnderFlowCb() const43 virtual void OnStreamBufferUnderFlowCb() const {}
OnStreamBufferOverFlowCb() const44 virtual void OnStreamBufferOverFlowCb() const {}
OnErrorCb(AudioServiceErrorCodes error) const45 virtual void OnErrorCb(AudioServiceErrorCodes error) const {}
OnEventCb(AudioServiceEventTypes error) const46 virtual void OnEventCb(AudioServiceEventTypes error) const {}
47 };
48
InitPlayback(std::unique_ptr<AudioServiceClient> & client,AudioStreamParams & audioParams)49 static int32_t InitPlayback(std::unique_ptr<AudioServiceClient> &client, AudioStreamParams &audioParams)
50 {
51 if (client == nullptr) {
52 AUDIO_ERR_LOG("Create AudioServiceClient instance failed");
53 return -1;
54 }
55
56 AUDIO_INFO_LOG("Initializing of AudioServiceClient");
57 if (client->Initialize(AUDIO_SERVICE_CLIENT_PLAYBACK) < 0)
58 return -1;
59
60 PlaybackTest customCb;
61 client->RegisterAudioRendererCallbacks(customCb);
62
63 AUDIO_INFO_LOG("Creating Stream");
64 if (client->CreateStream(audioParams, STREAM_MUSIC) < 0)
65 return -1;
66
67 AUDIO_INFO_LOG("Starting Stream");
68 if (client->StartStream() < 0)
69 return -1;
70
71 return 0;
72 }
73
StartPlayback(std::unique_ptr<AudioServiceClient> & client,FILE * wavFile)74 int32_t StartPlayback(std::unique_ptr<AudioServiceClient> &client, FILE *wavFile)
75 {
76 uint8_t* buffer = nullptr;
77 size_t n = 2;
78 size_t bytesToWrite = 0;
79 size_t bytesWritten = 0;
80 size_t minBytes = 4;
81 int32_t writeError;
82 uint64_t timeStamp = 0;
83 size_t bufferLen = 0;
84 StreamBuffer stream;
85
86 if (client->GetMinimumBufferSize(bufferLen) < 0) {
87 AUDIO_ERR_LOG(" GetMinimumBufferSize failed");
88 return -1;
89 }
90
91 AUDIO_DEBUG_LOG("minimum buffer length: %{public}zu", bufferLen);
92
93 buffer = (uint8_t *) malloc(n * bufferLen);
94 if (buffer == nullptr) {
95 AUDIO_ERR_LOG("Failed to allocate buffer");
96 return -1;
97 }
98
99 while (!feof(wavFile)) {
100 bytesToWrite = fread(buffer, 1, bufferLen, wavFile);
101 bytesWritten = 0;
102
103 while ((bytesWritten < bytesToWrite) && ((bytesToWrite - bytesWritten) > minBytes)) {
104 stream.buffer = buffer + bytesWritten;
105 stream.bufferLen = bytesToWrite - bytesWritten;
106 bytesWritten += client->WriteStream(stream, writeError);
107 if (client->GetCurrentTimeStamp(timeStamp) >= 0)
108 AUDIO_DEBUG_LOG("current timestamp: %{public}" PRIu64, timeStamp);
109 }
110 }
111
112 free(buffer);
113
114 return 0;
115 }
116
main(int argc,char * argv[])117 int main(int argc, char* argv[])
118 {
119 wav_hdr wavHeader;
120 size_t headerSize = sizeof(wav_hdr);
121 char *inputPath = argv[1];
122 char path[PATH_MAX + 1] = {0x00};
123 if ((strlen(inputPath) > PATH_MAX) || (realpath(inputPath, path) == nullptr)) {
124 AUDIO_ERR_LOG("Invalid path");
125 return -1;
126 }
127 AUDIO_INFO_LOG("path = %{public}s", path);
128 FILE* wavFile = fopen(path, "rb");
129 if (wavFile == nullptr) {
130 AUDIO_ERR_LOG("Unable to open wave file");
131 return -1;
132 }
133
134 float volume = 0.5;
135 if (argc >= ARGS_INDEX_THREE) {
136 volume = strtof(argv[ARGS_INDEX_TWO], nullptr);
137 }
138
139 size_t bytesRead = fread(&wavHeader, 1, headerSize, wavFile);
140 AUDIO_INFO_LOG("Header Read in bytes %{public}zu", bytesRead);
141 AudioStreamParams audioParams;
142 audioParams.format = DEFAULT_FORMAT;
143 audioParams.samplingRate = wavHeader.SamplesPerSec;
144 audioParams.channels = DEFAULT_CHANNELS;
145 std::unique_ptr<AudioServiceClient> client = std::make_unique<AudioStream>(STREAM_MUSIC, AUDIO_MODE_PLAYBACK,
146 getuid());
147 if (InitPlayback(client, audioParams) < 0) {
148 AUDIO_INFO_LOG("Initialize playback failed");
149 fclose(wavFile);
150 return -1;
151 }
152
153 AudioSystemManager *audioSystemMgr = AudioSystemManager::GetInstance();
154 audioSystemMgr->SetVolume(AudioVolumeType::STREAM_MUSIC, volume);
155
156 if (StartPlayback(client, wavFile) < 0) {
157 AUDIO_INFO_LOG("Start playback failed");
158 fclose(wavFile);
159 return -1;
160 }
161
162 client->FlushStream();
163 client->StopStream();
164 client->ReleaseStream();
165 fclose(wavFile);
166 AUDIO_INFO_LOG("Exit from test app");
167 return 0;
168 }
169