source: trunk/src/sample.cpp @ 2795

Last change on this file since 2795 was 2795, checked in by sam, 8 years ago

audio: report SDL mixer loading errors.

  • Property svn:keywords set to Id
File size: 4.4 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://www.wtfpl.net/ for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstdlib>
16#include <cstdio>
17#include <cstring>
18
19#if __CELLOS_LV2__
20#   include <cell/mstream.h> /* multistream */
21#elif defined USE_SDL_MIXER
22#   if defined HAVE_SDL_SDL_H
23#      include <SDL/SDL.h>
24#   else
25#      include <SDL.h>
26#   endif
27#   if defined HAVE_SDL_SDL_MIXER_H
28#      include <SDL/SDL_mixer.h>
29#   else
30#      include <SDL_mixer.h>
31#   endif
32#endif
33
34#include "core.h"
35
36using namespace std;
37
38namespace lol
39{
40
41/*
42 * Sample implementation class
43 */
44
45class SampleData
46{
47    friend class Sample;
48
49private:
50    String m_name;
51#if __CELLOS_LV2__
52    static void Callback(int stream, void *data, int type,
53                         void *write_buf, int buf_size)
54    {
55        UNUSED(write_buf, buf_size);
56        switch (type)
57        {
58        case CELL_MS_CALLBACK_MOREDATA:
59            /* For streamed sound */
60            break;
61        case CELL_MS_CALLBACK_CLOSESTREAM:
62        case CELL_MS_CALLBACK_FINISHSTREAM:
63            /* Finished playing */
64            break;
65        default:
66            /* FIXME: we can't reach here */
67            break;
68        }
69    }
70
71    String m_data;
72    int m_channel;
73#elif defined USE_SDL_MIXER
74    Mix_Chunk *m_chunk;
75    int m_channel;
76#endif
77};
78
79/*
80 * Public Sample class
81 */
82
83Sample::Sample(char const *path)
84  : data(new SampleData())
85{
86    data->m_name = String("<sample> ") + path;
87
88#if __CELLOS_LV2__
89    Array<String> pathlist = System::GetPathList(path);
90    File f;
91    for (int i = 0; i < pathlist.Count(); ++i)
92    {
93        f.Open(pathlist[i], FileAccess::Read);
94        if (f.IsValid())
95        {
96            data->m_data = f.ReadString();
97            f.Close();
98            break;
99        }
100    }
101    if (data->m_data.Count() == 0)
102    {
103        Log::Error("could not load sample %s\n", path);
104    }
105#elif defined USE_SDL_MIXER
106    Array<String> pathlist = System::GetPathList(path);
107    for (int i = 0; i < pathlist.Count(); ++i)
108    {
109        data->m_chunk = Mix_LoadWAV(pathlist[i].C());
110        if (data->m_chunk)
111            break;
112    }
113    if (!data->m_chunk)
114    {
115        Log::Error("could not load sample %s: %s\n", path, Mix_GetError());
116    }
117    data->m_channel = -1;
118#endif
119}
120
121Sample::~Sample()
122{
123#if __CELLOS_LV2__
124    /* Nothing to do */
125#elif defined USE_SDL_MIXER
126    if (data->m_chunk)
127        Mix_FreeChunk(data->m_chunk);
128#endif
129    delete data;
130}
131
132void Sample::TickGame(float seconds)
133{
134    Entity::TickGame(seconds);
135}
136
137char const *Sample::GetName()
138{
139    return data->m_name.C();
140}
141
142void Sample::Play()
143{
144#if __CELLOS_LV2__
145    if (data->m_data.Count() <= 64 + 256)
146        return;
147
148    data->m_channel = cellMSStreamOpen();
149
150    CellMSInfo mi;
151    mi.SubBusGroup = CELL_MS_MASTER_BUS;
152    mi.FirstBuffer = &data->m_data[0] + 64;
153    /* FIXME: hardcoded crap */
154    mi.FirstBufferSize = data->m_data.Count() - 64 - 256;
155    mi.SecondBuffer = nullptr;
156    mi.SecondBufferSize = 0;
157
158    mi.Pitch = 44100;
159    mi.numChannels = 2;
160    mi.flags = CELL_MS_STREAM_AUTOCLOSE;
161
162    mi.initialOffset = 0;
163    mi.inputType = CELL_MS_16BIT_LITTLE;
164    cellMSStreamSetInfo(data->m_channel, &mi);
165
166    cellMSStreamSetCallbackFunc(data->m_channel, SampleData::Callback);
167
168    cellMSCoreSetVolume1(data->m_channel, CELL_MS_DRY,
169                         CELL_MS_SPEAKER_FL, CELL_MS_CHANNEL_0, 1.0f);
170    cellMSCoreSetVolume1(data->m_channel, CELL_MS_DRY,
171                         CELL_MS_SPEAKER_FR, CELL_MS_CHANNEL_0, 1.0f);
172    cellMSStreamPlay(data->m_channel);
173#elif defined USE_SDL_MIXER
174    if (data->m_chunk)
175        data->m_channel = Mix_PlayChannel(-1, data->m_chunk, 0);
176#endif
177}
178
179void Sample::Loop()
180{
181#if __CELLOS_LV2__
182    /* FIXME: not implemented */
183    Play();
184#elif defined USE_SDL_MIXER
185    if (data->m_chunk)
186        data->m_channel = Mix_PlayChannel(-1, data->m_chunk, -1);
187#endif
188}
189
190void Sample::Stop()
191{
192#if __CELLOS_LV2__
193    if (data->m_channel >= 0)
194        cellMSStreamClose(data->m_channel);
195    data->m_channel = -1;
196#elif defined USE_SDL_MIXER
197    if (data->m_channel >= 0)
198        Mix_HaltChannel(data->m_channel);
199    data->m_channel = -1;
200#endif
201}
202
203} /* namespace lol */
204
Note: See TracBrowser for help on using the repository browser.