diff --git a/modules/client/client.lua b/modules/client/client.lua index c02d5c08..9641b0f0 100644 --- a/modules/client/client.lua +++ b/modules/client/client.lua @@ -1,30 +1,33 @@ -Client = {} +local musicFilename = "startup" +local musicChannel = g_sounds.getChannel(1) -local musicFilename = "startup.ogg" - -function Client.setMusic(filename) +function setMusic(filename) musicFilename = filename - g_sounds.stopMusic(0) if not g_game.isOnline() then - g_sounds.playMusic(musicFilename, 3) + musicChannel:stop() + musicChannel:enqueue(musicFilename, 3) end end -function Client.reloadScripts() +function reloadScripts() + g_textures.clearTexturesCache() g_modules.reloadModules() - dofile '/otclientrc' + dofile('/' .. g_app.getCompactName() .. 'rc') local message = tr('All modules and scripts were reloaded.') modules.game_textmessage.displayGameMessage(message) print(message) end -function Client.startup() +function startup() -- Play startup music (The Silver Tree, by Mattias Westlund) - g_sounds.playMusic(musicFilename, 3) - connect(g_game, { onGameStart = function() g_sounds.stopMusic(3) end }) - connect(g_game, { onGameEnd = function() g_sounds.playMusic(musicFilename, 3) end }) + musicChannel:enqueue(musicFilename, 3) + connect(g_game, { onGameStart = function() musicChannel:stop(3) end }) + connect(g_game, { onGameEnd = function() + g_sounds.stopAll() + musicChannel:enqueue(musicFilename, 3) + end }) -- Check for startup errors local errtitle = nil @@ -44,7 +47,7 @@ function Client.startup() end end -function Client.init() +function init() g_window.setMinimumSize({ width = 600, height = 480 }) g_sounds.preload(musicFilename) @@ -62,6 +65,8 @@ function Client.init() local defaultPos = { x = (displaySize.width - size.width)/2, y = (displaySize.height - size.height)/2 } local pos = g_settings.getPoint('window-pos', defaultPos) + pos.x = math.max(pos.x, 0) + pos.y = math.max(pos.y, 0) g_window.move(pos) -- window maximized? @@ -69,23 +74,25 @@ function Client.init() if maximized then g_window.maximize() end end - g_window.setTitle('OTClient') - g_window.setIcon(resolvepath('clienticon.png')) - g_keyboard.bindKeyDown('Ctrl+Shift+R', Client.reloadScripts) + g_window.setTitle(g_app.getName()) + g_window.setIcon(resolvepath('clienticon')) + + -- poll resize events + g_window.poll() - connect(g_app, { onRun = Client.startup }) + g_keyboard.bindKeyDown('Ctrl+Shift+R', reloadScripts) + + connect(g_app, { onRun = startup }) end -function Client.terminate() +function terminate() -- save window configs g_settings.set('window-size', g_window.getUnmaximizedSize()) g_settings.set('window-pos', g_window.getUnmaximizedPos()) g_settings.set('window-maximized', g_window.isMaximized()) - local protocolVersion = g_game.getProtocolVersion() - if protocolVersion ~= 0 then - g_settings.set('protocol-version', protocolVersion) + local clientVersion = g_game.getProtocolVersion() + if clientVersion ~= 0 then + g_settings.set('client-version', clientVersion) end - - Client = nil end diff --git a/modules/client/client.otmod b/modules/client/client.otmod index ee107b4e..539e794f 100644 --- a/modules/client/client.otmod +++ b/modules/client/client.otmod @@ -4,6 +4,10 @@ Module author: edubart website: www.otclient.info reloadable: false + sandboxed: true + scripts: [ client ] + @onLoad: init() + @onUnload: terminate() load-later: - client_skins @@ -18,9 +22,3 @@ Module - client_exit //- client_stats - @onLoad: | - dofile 'client' - Client.init() - - @onUnload: | - Client.terminate() diff --git a/modules/client_options/options.lua b/modules/client_options/options.lua index b8ea319f..37cb2f1a 100644 --- a/modules/client_options/options.lua +++ b/modules/client_options/options.lua @@ -184,7 +184,7 @@ function Options.setOption(key, value) modules.game_interface.updateStretchShrink() end) elseif key == 'enableMusic' then - g_sounds.enableMusic(value) + g_sounds.enableAudio(value) elseif key == 'showLeftPanel' then addEvent(function() modules.game_interface.getLeftPanel():setOn(value) diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 59f106d2..b11592af 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -426,6 +426,8 @@ if(FRAMEWORK_SOUND) ${CMAKE_CURRENT_LIST_DIR}/sound/oggsoundfile.h ${CMAKE_CURRENT_LIST_DIR}/sound/soundbuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/sound/soundbuffer.h + ${CMAKE_CURRENT_LIST_DIR}/sound/soundchannel.cpp + ${CMAKE_CURRENT_LIST_DIR}/sound/soundchannel.h ${CMAKE_CURRENT_LIST_DIR}/sound/soundfile.cpp ${CMAKE_CURRENT_LIST_DIR}/sound/soundfile.h ${CMAKE_CURRENT_LIST_DIR}/sound/soundmanager.cpp diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 46cdce33..b749e823 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -34,6 +34,14 @@ #include #include +#ifdef FW_SOUND +#include +#include +#include +#include +#include +#endif + #ifdef FW_GRAPHICS #include #include @@ -759,15 +767,29 @@ void Application::registerLuaFunctions() // SoundManager g_lua.registerSingletonClass("g_sounds"); g_lua.bindSingletonFunction("g_sounds", "preload", &SoundManager::preload, &g_sounds); - g_lua.bindSingletonFunction("g_sounds", "enableSound", &SoundManager::enableSound, &g_sounds); g_lua.bindSingletonFunction("g_sounds", "play", &SoundManager::play, &g_sounds); - g_lua.bindSingletonFunction("g_sounds", "enableMusic", &SoundManager::enableMusic, &g_sounds); - g_lua.bindSingletonFunction("g_sounds", "playMusic", &SoundManager::playMusic, &g_sounds); - g_lua.bindSingletonFunction("g_sounds", "stopMusic", &SoundManager::stopMusic, &g_sounds); - g_lua.bindSingletonFunction("g_sounds", "isMusicEnabled", &SoundManager::isMusicEnabled, &g_sounds); - g_lua.bindSingletonFunction("g_sounds", "isSoundEnabled", &SoundManager::isSoundEnabled, &g_sounds); + g_lua.bindSingletonFunction("g_sounds", "getChannel", &SoundManager::getChannel, &g_sounds); + g_lua.bindSingletonFunction("g_sounds", "stopAll", &SoundManager::stopAll, &g_sounds); + g_lua.bindSingletonFunction("g_sounds", "enableAudio", &SoundManager::enableAudio, &g_sounds); + g_lua.bindSingletonFunction("g_sounds", "disableAudio", &SoundManager::disableAudio, &g_sounds); + g_lua.bindSingletonFunction("g_sounds", "setAudioEnabled", &SoundManager::setAudioEnabled, &g_sounds); g_lua.bindSingletonFunction("g_sounds", "isAudioEnabled", &SoundManager::isAudioEnabled, &g_sounds); - g_lua.bindSingletonFunction("g_sounds", "getCurrentMusic", &SoundManager::getCurrentMusic, &g_sounds); + + g_lua.registerClass(); + g_lua.registerClass(); + g_lua.registerClass(); + + g_lua.registerClass(); + g_lua.bindClassMemberFunction("play", &SoundChannel::play); + g_lua.bindClassMemberFunction("stop", &SoundChannel::stop); + g_lua.bindClassMemberFunction("enqueue", &SoundChannel::enqueue); + g_lua.bindClassMemberFunction("enable", &SoundChannel::enable); + g_lua.bindClassMemberFunction("disable", &SoundChannel::disable); + g_lua.bindClassMemberFunction("setGain", &SoundChannel::setGain); + g_lua.bindClassMemberFunction("getGain", &SoundChannel::getGain); + g_lua.bindClassMemberFunction("setEnabled", &SoundChannel::setEnabled); + g_lua.bindClassMemberFunction("isEnabled", &SoundChannel::isEnabled); + g_lua.bindClassMemberFunction("getId", &SoundChannel::getId); #endif #ifdef FW_SQL diff --git a/src/framework/sound/declarations.h b/src/framework/sound/declarations.h index 794d13a7..5877ef30 100644 --- a/src/framework/sound/declarations.h +++ b/src/framework/sound/declarations.h @@ -34,6 +34,7 @@ class SoundManager; class SoundSource; class SoundBuffer; class SoundFile; +class SoundChannel; class StreamSoundSource; class CombinedSoundSource; class OggSoundFile; @@ -41,6 +42,7 @@ class OggSoundFile; typedef stdext::shared_object_ptr SoundSourcePtr; typedef stdext::shared_object_ptr SoundFilePtr; typedef stdext::shared_object_ptr SoundBufferPtr; +typedef stdext::shared_object_ptr SoundChannelPtr; typedef stdext::shared_object_ptr StreamSoundSourcePtr; typedef stdext::shared_object_ptr CombinedSoundSourcePtr; typedef stdext::shared_object_ptr OggSoundFilePtr; diff --git a/src/framework/sound/soundmanager.cpp b/src/framework/sound/soundmanager.cpp index a0f5077a..e8ee7d35 100644 --- a/src/framework/sound/soundmanager.cpp +++ b/src/framework/sound/soundmanager.cpp @@ -46,21 +46,21 @@ void SoundManager::init() g_logger.error(stdext::format("unable to create audio context: %s", alcGetString(m_device, alcGetError(m_device)))); return; } - alcMakeContextCurrent(m_context); - m_musicEnabled = true; - m_soundEnabled = true; + if(alcMakeContextCurrent(m_context) != ALC_TRUE) { + g_logger.error(stdext::format("unable to make context current: %s", alcGetString(m_device, alcGetError(m_device)))); + return; + } } void SoundManager::terminate() { + ensureContext(); + m_sources.clear(); m_buffers.clear(); - m_musicSource = nullptr; - m_currentMusic = ""; - - m_musicEnabled = false; - m_soundEnabled = false; + m_channels.clear(); + m_audioEnabled = false; alcMakeContextCurrent(nullptr); @@ -85,6 +85,7 @@ void SoundManager::poll() lastUpdate = now; + ensureContext(); for(auto it = m_sources.begin(); it != m_sources.end();) { SoundSourcePtr source = *it; @@ -96,10 +97,8 @@ void SoundManager::poll() ++it; } - if(m_musicSource) { - m_musicSource->update(); - if(!m_musicSource->isPlaying()) - m_musicSource = nullptr; + for(auto it : m_channels) { + it.second->update(); } if(m_context) { @@ -107,18 +106,33 @@ void SoundManager::poll() } } +void SoundManager::setAudioEnabled(bool enable) +{ + if(m_audioEnabled == enable) + return; + + m_audioEnabled = enable; + if(!enable) { + ensureContext(); + for(const SoundSourcePtr& source : m_sources) { + source->stop(); + } + } +} + void SoundManager::preload(std::string filename) { - filename = g_resources.resolvePath(filename); + filename = resolveSoundFile(filename); auto it = m_buffers.find(filename); if(it != m_buffers.end()) return; + ensureContext(); SoundFilePtr soundFile = SoundFile::loadSoundFile(filename); // only keep small files - if(soundFile->getSize() > MAX_CACHE_SIZE) + if(!soundFile || soundFile->getSize() > MAX_CACHE_SIZE) return; SoundBufferPtr buffer = SoundBufferPtr(new SoundBuffer); @@ -126,85 +140,55 @@ void SoundManager::preload(std::string filename) m_buffers[filename] = buffer; } -void SoundManager::enableSound(bool enable) +SoundSourcePtr SoundManager::play(std::string filename, float fadetime, float gain) { - if(!isAudioEnabled()) - return; -} + if(!m_audioEnabled) + return nullptr; -void SoundManager::play(std::string filename) -{ - if(!m_soundEnabled || filename.empty()) - return; + ensureContext(); - filename = g_resources.resolvePath(filename); + if(gain == 0) + gain = 1.0f; + filename = resolveSoundFile(filename); SoundSourcePtr soundSource = createSoundSource(filename); if(!soundSource) { g_logger.error(stdext::format("unable to play '%s'", filename)); - return; + return nullptr; } + soundSource->setName(filename); soundSource->setRelative(true); + soundSource->setGain(gain); + + if(fadetime > 0) { + soundSource->setFading(StreamSoundSource::FadingOn, fadetime); + } + soundSource->play(); m_sources.push_back(soundSource); + + return soundSource; } -void SoundManager::enableMusic(bool enable) +SoundChannelPtr SoundManager::getChannel(int channel) { - if(!isAudioEnabled()) - return; - - m_musicEnabled = enable; - - if(enable && !m_currentMusic.empty()) - playMusic(m_currentMusic, 3.0f); - else - m_musicSource = nullptr; + ensureContext(); + if(!m_channels[channel]) + m_channels[channel] = SoundChannelPtr(new SoundChannel(channel)); + return m_channels[channel]; } -void SoundManager::playMusic(std::string filename, float fadetime) +void SoundManager::stopAll() { - if(filename.empty()) - return; - - filename = g_resources.resolvePath(filename); - - if(m_currentMusic == filename && m_musicSource) - return; - - if(!m_musicEnabled) - return; - - if(filename.empty()) { - m_musicSource = nullptr; - return; + ensureContext(); + for(const SoundSourcePtr& source : m_sources) { + source->stop(); } - m_musicSource = createSoundSource(filename); - if(!m_musicSource) { - g_logger.error(stdext::format("unable to play '%s'", filename)); - return; - } - - m_musicSource->setRelative(true); - - if(fadetime > 0) { - m_musicSource->setGain(0); - m_musicSource->setFading(StreamSoundSource::FadingOn, fadetime); - } - - m_musicSource->play(); -} - -void SoundManager::stopMusic(float fadetime) -{ - if(m_musicSource) { - if(fadetime > 0) - m_musicSource->setFading(StreamSoundSource::FadingOff, 3.0f); - else - m_musicSource->stop(); + for(auto it : m_channels) { + it.second->stop(); } } @@ -212,51 +196,69 @@ SoundSourcePtr SoundManager::createSoundSource(const std::string& filename) { SoundSourcePtr source; - auto it = m_buffers.find(filename); - if(it != m_buffers.end()) { - source = SoundSourcePtr(new SoundSource); - source->setBuffer(it->second); - } else { - SoundFilePtr soundFile = SoundFile::loadSoundFile(filename); - if(!soundFile) - return nullptr; - - if(soundFile->getSize() <= MAX_CACHE_SIZE) { + try { + auto it = m_buffers.find(filename); + if(it != m_buffers.end()) { source = SoundSourcePtr(new SoundSource); - SoundBufferPtr buffer = SoundBufferPtr(new SoundBuffer); - buffer->fillBuffer(soundFile); - source->setBuffer(buffer); - m_buffers[filename] = buffer; - g_logger.warning(stdext::format("uncached sound '%s' requested to be played", filename)); + source->setBuffer(it->second); } else { - StreamSoundSourcePtr streamSource(new StreamSoundSource); - streamSource->setSoundFile(soundFile); - source = streamSource; - -#if defined __linux && !defined OPENGL_ES - // due to OpenAL implementation bug, stereo buffers are always downmixed to mono on linux systems - // this is hack to work around the issue - // solution taken from http://opensource.creative.com/pipermail/openal/2007-April/010355.html - if(soundFile->getSampleFormat() == AL_FORMAT_STEREO16) { - CombinedSoundSourcePtr combinedSource(new CombinedSoundSource); - - streamSource->downMix(StreamSoundSource::DownMixLeft); - streamSource->setRelative(true); - streamSource->setPosition(Point(-128, 0)); - combinedSource->addSource(streamSource); - - streamSource = StreamSoundSourcePtr(new StreamSoundSource); - streamSource->setSoundFile(SoundFile::loadSoundFile(filename)); - streamSource->downMix(StreamSoundSource::DownMixRight); - streamSource->setRelative(true); - streamSource->setPosition(Point(128,0)); - combinedSource->addSource(streamSource); - - source = combinedSource; + SoundFilePtr soundFile = SoundFile::loadSoundFile(filename); + if(!soundFile) + return nullptr; + + if(soundFile->getSize() <= MAX_CACHE_SIZE) { + source = SoundSourcePtr(new SoundSource); + SoundBufferPtr buffer = SoundBufferPtr(new SoundBuffer); + buffer->fillBuffer(soundFile); + source->setBuffer(buffer); + m_buffers[filename] = buffer; + g_logger.warning(stdext::format("uncached sound '%s' requested to be played", filename)); + } else { + StreamSoundSourcePtr streamSource(new StreamSoundSource); + streamSource->setSoundFile(soundFile); + source = streamSource; + + #if defined __linux && !defined OPENGL_ES + // due to OpenAL implementation bug, stereo buffers are always downmixed to mono on linux systems + // this is hack to work around the issue + // solution taken from http://opensource.creative.com/pipermail/openal/2007-April/010355.html + if(soundFile->getSampleFormat() == AL_FORMAT_STEREO16) { + CombinedSoundSourcePtr combinedSource(new CombinedSoundSource); + + streamSource->downMix(StreamSoundSource::DownMixLeft); + streamSource->setRelative(true); + streamSource->setPosition(Point(-128, 0)); + combinedSource->addSource(streamSource); + + streamSource = StreamSoundSourcePtr(new StreamSoundSource); + streamSource->setSoundFile(SoundFile::loadSoundFile(filename)); + streamSource->downMix(StreamSoundSource::DownMixRight); + streamSource->setRelative(true); + streamSource->setPosition(Point(128,0)); + combinedSource->addSource(streamSource); + + source = combinedSource; + } + #endif } -#endif } + } catch(std::exception& e) { + g_logger.error(stdext::format("failed to load sound source: '%s'", e.what())); + return nullptr; } return source; } + +std::string SoundManager::resolveSoundFile(std::string file) +{ + file = g_resources.guessFileType(file, "ogg"); + file = g_resources.resolvePath(file); + return file; +} + +void SoundManager::ensureContext() +{ + if(m_context) + alcMakeContextCurrent(m_context); +} diff --git a/src/framework/sound/soundmanager.h b/src/framework/sound/soundmanager.h index 2a8bf15a..2c615f69 100644 --- a/src/framework/sound/soundmanager.h +++ b/src/framework/sound/soundmanager.h @@ -24,6 +24,7 @@ #define SOUNDMANAGER_H #include "declarations.h" +#include "soundchannel.h" //@bindsingleton g_sounds class SoundManager @@ -32,38 +33,34 @@ class SoundManager MAX_CACHE_SIZE = 100000, POLL_DELAY = 100 }; - public: void init(); void terminate(); void poll(); - void preload(std::string filename); - void enableSound(bool enable); - void play(std::string filename); + void setAudioEnabled(bool enable); + bool isAudioEnabled() { return m_device && m_context && m_audioEnabled ; } + void enableAudio() { setAudioEnabled(true); } + void disableAudio() { setAudioEnabled(true); } + void stopAll(); - void enableMusic(bool enable); - void playMusic(std::string filename, float fadetime); - void stopMusic(float fadetime = 0); + void preload(std::string filename); + SoundSourcePtr play(std::string filename, float fadetime = 0, float gain = 0); + SoundChannelPtr getChannel(int channel); - bool isMusicEnabled() { return m_musicEnabled; } - bool isSoundEnabled() { return m_soundEnabled; } - bool isAudioEnabled() { return m_device && m_context; } - std::string getCurrentMusic() { return m_currentMusic; } + std::string resolveSoundFile(std::string file); + void ensureContext(); private: - StreamSoundSourcePtr createStreamSoundSource(const std::string& filename); SoundSourcePtr createSoundSource(const std::string& filename); - uint loadFileIntoBuffer(const SoundFilePtr& soundFile); - std::unordered_map m_buffers; - std::vector m_sources; - SoundSourcePtr m_musicSource; ALCdevice *m_device; ALCcontext *m_context; - stdext::boolean m_musicEnabled; - stdext::boolean m_soundEnabled; - std::string m_currentMusic; + + std::unordered_map m_buffers; + std::vector m_sources; + stdext::boolean m_audioEnabled; + std::unordered_map m_channels; }; extern SoundManager g_sounds; diff --git a/src/framework/sound/soundsource.cpp b/src/framework/sound/soundsource.cpp index 3bd4a3c7..f7d7677c 100644 --- a/src/framework/sound/soundsource.cpp +++ b/src/framework/sound/soundsource.cpp @@ -28,9 +28,12 @@ SoundSource::SoundSource() { m_sourceId = 0; + m_channel = 0; m_fadeState = NoFading; m_fadeTime = 0; m_fadeStartTime = 0; + m_fadeGain = 0; + m_gain = 1.0f; alGenSources(1, &m_sourceId); assert(alGetError() == AL_NO_ERROR); @@ -95,6 +98,7 @@ void SoundSource::setReferenceDistance(float distance) void SoundSource::setGain(float gain) { alSourcef(m_sourceId, AL_GAIN, gain); + m_gain = gain; } void SoundSource::setPitch(float pitch) @@ -114,7 +118,7 @@ void SoundSource::setVelocity(const Point& velocity) void SoundSource::setFading(FadeState state, float fadeTime) { - float now = g_clock.seconds(); + float now = stdext::millis() / 1000.0f; if(m_fadeState != NoFading) { float elapsed = now - m_fadeStartTime; float add; @@ -128,26 +132,30 @@ void SoundSource::setFading(FadeState state, float fadeTime) m_fadeState = state; m_fadeTime = fadeTime; + m_fadeGain = m_gain; + + if(m_fadeState == FadingOn) + setGain(0.0); } void SoundSource::update() { - float now = g_clock.seconds(); + float now = stdext::millis() / 1000.0f; if(m_fadeState == FadingOn) { float elapsed = now - m_fadeStartTime; if(elapsed >= m_fadeTime) { - setGain(1.0); m_fadeState = NoFading; } else { - setGain(elapsed / m_fadeTime); + setGain((elapsed / m_fadeTime) * m_fadeGain); } } else if(m_fadeState == FadingOff) { - float time = now - m_fadeStartTime; - if(time >= m_fadeTime) { + float elapsed = now - m_fadeStartTime; + if(elapsed >= m_fadeTime) { + setGain(m_fadeGain); stop(); m_fadeState = NoFading; } else { - setGain((m_fadeTime - time) / m_fadeTime); + setGain(((m_fadeTime - elapsed) / m_fadeTime) * m_fadeGain); } } } diff --git a/src/framework/sound/soundsource.h b/src/framework/sound/soundsource.h index c985a93d..56bed5ad 100644 --- a/src/framework/sound/soundsource.h +++ b/src/framework/sound/soundsource.h @@ -25,8 +25,9 @@ #include "declarations.h" #include "soundbuffer.h" +#include -class SoundSource : public stdext::shared_object +class SoundSource : public LuaObject { protected: SoundSource(uint sourceId) : m_sourceId(sourceId) { } @@ -43,6 +44,7 @@ public: virtual bool isBuffering(); virtual bool isPlaying() { return isBuffering(); } + void setName(const std::string& name) { m_name == name; } virtual void setLooping(bool looping); virtual void setRelative(bool relative); virtual void setReferenceDistance(float distance); @@ -52,18 +54,27 @@ public: virtual void setVelocity(const Point& velocity); virtual void setFading(FadeState state, float fadetime); + std::string getName() { return m_name; } + uchar getChannel() { return m_channel; } + float getGain() { return m_gain; } + protected: void setBuffer(const SoundBufferPtr& buffer); + void setChannel(uchar channel) { m_channel = channel; } virtual void update(); friend class SoundManager; friend class CombinedSoundSource; uint m_sourceId; + uchar m_channel; + std::string m_name; SoundBufferPtr m_buffer; FadeState m_fadeState; float m_fadeStartTime; float m_fadeTime; + float m_fadeGain; + float m_gain; }; #endif diff --git a/src/framework/sound/streamsoundsource.h b/src/framework/sound/streamsoundsource.h index 1a0e4593..46686bfa 100644 --- a/src/framework/sound/streamsoundsource.h +++ b/src/framework/sound/streamsoundsource.h @@ -28,8 +28,8 @@ class StreamSoundSource : public SoundSource { enum { - STREAM_BUFFER_SIZE = 1024 * 200, - STREAM_FRAGMENTS = 5, + STREAM_BUFFER_SIZE = 1024 * 400, + STREAM_FRAGMENTS = 4, STREAM_FRAGMENT_SIZE = STREAM_BUFFER_SIZE / STREAM_FRAGMENTS };