I have the following sound loading function:
bool Sound::load(const char* fileName)
{
sound = Mix_LoadWAV(fileName);
if (sound == nullptr)
{
std::cout << "Failed to load sound at path: " << fileName << "SDL_mixer error: " << Mix_GetError();
return false;
}
return true;
}
In Dev-C++, this works, fine. I wanted to use another IDE, so I started using Visual Studio 2017, and configured SDL2 for it. However, when I run this code, from the moment Mix_LoadWAV is called, Visual studio gives the following:
https://imgur.com/a/STnXx
I have searched alot on the internet, but I could not find anything useful that worked for me.
EDIT: as per request, I created a minimal example that still produces the same error.
#include "SDL2\SDL_mixer.h"
#include "SDL2\SDL.h"
#include <iostream>
#undef main
class SoundTest
{
private:
Mix_Chunk* sound = nullptr;
public:
bool load(const char* fileName)
{
sound = Mix_LoadWAV(fileName);
if (sound == nullptr)
{
std::cout << "Failed to load sound at path: " << fileName << "SDL_mixer error: " << Mix_GetError();
return false;
}
return true;
}
};
SDL_Window *window = nullptr;
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("Sound bug? ", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 300, 300, SDL_WINDOW_SHOWN);
Mix_OpenAudio(22050, MIX_DEFAULT_FORMAT, 2, 2048);
SoundTest sound;
sound.load("audio/soundEffect.wav");
while (true)
{
//Do fun stuff with the sound
}
return 0;
}
Related
I would like to record a rosbag file with a specific name; however, I only know it after the recording is halfway done, so I cannot set the filename here:
cfg.enable_record_to_file("some/path/filename.bag");
I have tried to rename the new file as shown below without satisfactory success. I have also used std::experimental::filesystem::rename, with the same outcome. What did work was to record a second video (on the fly) and only then rename the first. This indicates that the (both) rename functions work, but I cannot change the filename it as it seems the file is still open in my current program.
int main(int argc, char* argv[])
{
rs2::config cfg;
rs2::device device;
auto pipe = std::make_shared<rs2::pipeline>();
cfg.disable_all_streams();
cfg.enable_stream(RS2_STREAM_DEPTH, 640, 480, RS2_FORMAT_Z16, 30);
cfg.enable_record_to_file("tmp.bag");
pipe->start(cfg);
device = pipe->get_active_profile().get_device();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
device.as<rs2::recorder>().pause();
pipe->stop();
int res = std::rename("tmp.bag", "test.bag");
if (res == 0)
std::cout << "File successfully renamed" << std::endl;
else
std::cout << "Error renaming file" << std::endl;
return 0;
}
I wonder how to 'unload' the produced video from the pipeline (pipe->stop() did not work), so I can rename the generated rosbag files on the fly.
As suggested by #TedLyngmo, adding curly brackets allowed me to change the filename on the fly. Code as follows:
int main(int argc, char* argv[])
{
{
rs2::config cfg;
rs2::device device;
auto pipe = std::make_shared<rs2::pipeline>();
cfg.disable_all_streams();
cfg.enable_stream(RS2_STREAM_DEPTH, 640, 480, RS2_FORMAT_Z16, 30);
cfg.enable_record_to_file("tmp.bag");
pipe->start(cfg);
device = pipe->get_active_profile().get_device();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
device.as<rs2::recorder>().pause();
pipe->stop();
}
int res = std::rename("tmp.bag", "test.bag");
if (res == 0)
std::cout << "File successfully renamed" << std::endl;
else
std::cout << "Error renaming file" << std::endl;
return 0;
}
EDIT
I studied rs-record-playback a bit more and the code below fixes the renaming issue.
int main(int argc, char* argv[])
{
rs2::device device;
auto pipe = std::make_shared<rs2::pipeline>();
pipe->start();
device = pipe->get_active_profile().get_device();
if (!device.as<rs2::recorder>())
{
pipe->stop(); // Stop the pipeline with the default configuration
pipe = std::make_shared<rs2::pipeline>();
rs2::config cfg;
cfg.disable_all_streams();
cfg.enable_stream(RS2_STREAM_DEPTH, 640, 480, RS2_FORMAT_Z16, 30);
cfg.enable_record_to_file("tmp.bag");
pipe->start(cfg);
device = pipe->get_active_profile().get_device();
}
// record for 1 sec, if conditions can be added to check if recorder is initialised
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
// if condition can be added to check if recording has been completed
pipe->stop();
pipe = std::make_shared<rs2::pipeline>(); // reset the shared pointer
pipe->start();
device = pipe->get_active_profile().get_device();
int res = std::rename("tmp.bag", "testing.bag");
if (res == 0)
std::cout << "File successfully renamed" << std::endl;
else
std::cout << "Error renaming file" << std::endl;
pipe->stop();
pipe = std::make_shared<rs2::pipeline>();
}
I'm working on a small project in CLion with SDL2 on Windows.
When I compile and run (Shift+F10) my program in CLion, it does not show any console output. However, when I run it using the debugger (Shift+F9), it does show console output..
I have no idea what is causing this.
To make sure my project or CLion isn't corrupting something, I've copied the sources over to a new project and set it up using the same CMakeList.txt file, and it still does not work.
My CMakeList.txt:
CMakeList.txt
cmake_minimum_required(VERSION 3.6)
project(SDL_Project)
set(CMAKE_CXX_STANDARD 14)
# FindSDL2.cmake
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
#find_package(SDL2_ttf REQUIRED)
include_directories(${SDL2_INCLUDE_DIR})
include_directories(${SDL2_IMAGE_INCLUDE_DIR})
#include_directories(${SDL2_TTF_INCLUDE_DIR})
add_executable(SDL_Project src/main.cpp src/Game.cpp src/Game.h)
set_target_properties(SDL_Project PROPERTIES WIN32_EXECUTABLE FALSE)
target_link_libraries(SDL_Project ${SDL2_LIBRARY})
target_link_libraries(SDL_Project ${SDL2_IMAGE_LIBRARIES})
#target_link_libraries(SDL_Project ${SDL2_TTF_LIBRARIES})
I also tried compiling the following code (without SDL2, but using the same CMakeList.txt):
#include <iostream>
int main(int argv, char* args[]) {
std::cout << "Hello World!" << std::endl;
return 0;
}
This has the same issue; no console output.
Compiling the above code without the find_package, include_directories and target_link_libraries in CMakeList.txt shows console output! So it is related to SDL2, I think..?
Does anyone know what is causing this, and how to fix it?
Though I believe the problem lies in CMakeList.txt, here is the remaining code:
main.cpp
#include <SDL.h>
#include <iostream>
#include "Game.h"
int main(int argv, char* args[]) {
const int FPS = 60;
const uint32_t frameDelay = 1000 / FPS;
const WindowSettings settings = {SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 720};
Game game;
Uint32 frameStart;
Uint32 frameTime;
game.init("Game", settings);
while (game.isRunning()) {
frameStart = SDL_GetTicks();
game.handleEvents();
game.tick();
game.render();
frameTime = SDL_GetTicks() - frameStart;
std::cout << "Frame time: " << frameTime << " / " << frameDelay << std::endl;
if (frameTime < frameDelay) {
std::cout << "Frame delay: " << (frameDelay - frameTime) << std::endl;
SDL_Delay(frameDelay - frameTime);
}
}
game.cleanup();
return 0;
}
Game.h
#ifndef SDL_PROJECT_GAME_H
#define SDL_PROJECT_GAME_H
#include <SDL.h>
struct WindowSettings {
int x;
int y;
int width;
int height;
};
class Game {
private:
bool running;
SDL_Window* window;
SDL_Renderer* renderer;
public:
Game();
~Game();
void init(const char* title, const WindowSettings &settings);
void tick();
void render();
void cleanup();
void handleEvents();
bool isRunning() { return running; }
};
#endif //SDL_PROJECT_GAME_H
Game.cpp
#include <iostream>
#include "Game.h"
Game::Game():
running(false),
window(nullptr),
renderer(nullptr) {
}
Game::~Game() = default;
void Game::init(const char *title, const WindowSettings &settings) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "SDL initialization failed: " << SDL_GetError() << std::endl;
return;
};
window = SDL_CreateWindow(title, settings.x, settings.y, settings.width, settings.height, SDL_WINDOW_SHOWN);
if (window == nullptr) {
std::cout << "Unable to create window: " << SDL_GetError() << std::endl;
return;
}
renderer = SDL_CreateRenderer(window, -1 , 0);
if (renderer == nullptr) {
std::cout << "Unable to create renderer: " << SDL_GetError() << std::endl;
return;
}
running = true;
}
void Game::tick() {
}
void Game::render() {
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
void Game::cleanup() {
if (renderer) {
SDL_DestroyRenderer(renderer);
}
if (window) {
SDL_DestroyWindow(window);
}
SDL_Quit();
std::cout << "Game clean exit" << std::endl;
}
void Game::handleEvents() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
}
}
}
I can think of 1 issue. Are you sure your run configuration is correct CLION? The debug build could be running a different executable than you think. CLION does a lot of stuff behind the scenes. Click the run arrow drop down and look at edit configurations or something to that effect.
Alright, I figured it out..
Apparently, compiling on Windows redirects stdout and stderr to null (?). I was unable to locate/remove the compiler flag that influences this, however, SDL provides SDL_Log, which does in fact output to the console (and presumably stdout?).
Since I'm using SDL2 anyway, I might as well use the logger. It supports printf-style formatting, which is a nice bonus. And it allows me to set up a custom logging function if I want to redirect log messages.
I have been trying for hours to get a test SDL program up and running, but no matter what I try, it instantly terminates upon launching.
My code:
#include <iostream>
#include <SDL.h>
#undef main
using namespace std;
int main(int argc, char *argv[]) {
const int WIDTH = 800, HEIGHT = 600, SDLWP = SDL_WINDOWPOS_UNDEFINED;
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
cout << "SDL not working." << endl;
}
cout << "SDL working properly." << endl;
SDL_Window *window = SDL_CreateWindow("Test", SDLWP, SDLWP, WIDTH, HEIGHT, SDL_WINDOW_SHOWN);
if(window == NULL) {
SDL_Quit();
}
bool quit = false;
SDL_Event event;
while(!quit) {
while(SDL_PollEvent(&event)) {
if(event.type == SDL_QUIT) {
quit = true;
}
}
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
I have gotten the program to actually do something by having this code:
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
cout << "SDL working properly." << endl;
}
Also, about the #undef main part, I need that because otherwise, the program will think that I am calling SDL_main.
Here is the library search path if that helps:
C:\Users\ (my username)\Desktop\SDL2-2.0.4\i686-w64-mingw32\lib
And the libraries themselves, written in order from top to bottom:
mingw32
SDL2main
SDL2
No other library path will give me no compiler errors except:
C:\Users\ (my username)\Desktop\SDL2-2.0.4\lib\x86
So it seems that the root of problem is:
#include <SDL.h>
So I'm having issues with SDL_mixer, and it seems it plays fine on a good amount of mp3s (although "fine". I noticed that at the beginning of some MP3s there's a small segment of sound corruption, and then it starts playing) but on some MP3 files, there's just absolute silence. It doesn't seem to play anything. And Mix_PlayMusic doesn't seem to return an error, nor does anything else, but it just seems to not make a single sound. Occasionally I'll get a random "Access Reading Violation" when trying to play those files, but every other time, it's just silence.
Here is the code that I'm using to play the MP3 file:
#include "SDL.h"
#include "SDL_mixer.h"
#include <iostream>
bool initLibs()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return false;
}
int flags = MIX_INIT_MP3 | MIX_INIT_OGG;
if(Mix_Init(flags)!=flags)
{
return false;
}
//Initialize SDL_mixer
if( Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, AUDIO_S16, 2, 4096 ) == -1 )
{
return false;
}
//If everything initialized fine
return true;
}
int main(int argc, char* argv[])
{
if(!initLibs())
{
std::cout << "error loading libraries" << std::endl;
}
Mix_Music* music = Mix_LoadMUS("test.mp3");
if(music == nullptr)
{
std::cout << "error loading music: " << Mix_GetError() << std::endl;
}
else
{
if(Mix_PlayMusic(music, -1) == -1)
{
std::cout << "error playing music: " << Mix_GetError() << std::endl;
}
}
SDL_Delay(30000);
system("PAUSE");
Mix_HaltMusic();
Mix_FreeMusic(music);
system("PAUSE");
return 0;
}
I was examining the differences in the MP3 files, and it seems that the only real difference is that the ones with LAME3.99 encoding are the ones that don't seem to work. Is anybody able to explain this?
EDIT: After more testing, it also seems to happen on other ones
I read and tried all the other posts to that topic, but nothing helped. When I try to play music with Mix_PlayChannel() I don't get an error nor do I hear some sound! I tried for hours now and nothing helps. The program just finishes happily. But no sound! I am using Ubuntu 12.04 64bit.
Thanks!
[EDIT]
Here is the code I use:
#include <iostream>
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
int main(int argc, char** argv) {
Mix_Music *music = NULL;
Mix_Chunk *wave = NULL;
SDL_Init(SDL_INIT_AUDIO);
int audio_rate = 44100;
Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */
int audio_channels = 1;
int audio_buffers = 4096;
if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) {
printf("Unable to open audio!\n");
exit(1);
}
if(Mix_Init(MIX_INIT_MOD) != MIX_INIT_MOD)
std::cout << "errer";
Mix_Volume(-1, MIX_MAX_VOLUME);
music = Mix_LoadMUS("1.wav");
wave = Mix_LoadWAV("1.wav");
if (music == NULL) {
std::cout << "Could not load 1.wav\n";
std::cout << Mix_GetError();
}
if (wave == NULL) {
std::cout << "Could not load 1.wav\n";
std::cout << Mix_GetError();
}
Mix_VolumeChunk(wave, MIX_MAX_VOLUME);
Mix_VolumeMusic(MIX_MAX_VOLUME);
Mix_PlayMusic(music, 0);
std::cout << Mix_GetError();
Mix_FadeInChannelTimed(-1, wave, 0, 100,1);
std::cout << Mix_GetError();
return 1;
}
I try both PlayMusic() and Mix_FadeInChannelTimed(). Both files are loaded correctly but not played. Sound is not muted, wav-file is playable with aplay or other tools. I check with alsamixer that all channels are open and not too low.
I now found out that the program needs to run until the sound has finished playing! I added a usleep() command after the play command and it plays nicely. So that was really mentioned nowhere that PlayMusic() does not keep running.