• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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