[SOLVED] How to Build libopenmpt without XCode on OSX?

Started by ryansupak, May 06, 2020, 03:21:50

Previous topic - Next topic

ryansupak

Hi, Just starting out with libopenmpt so pardon my novice-ness! ;D




I have downloaded the Source Code for libopenmpt and I am trying to build it for an OSX environment. (I don't want to use Xcode). I tried the following steps:

1) Downloaded the latest Autotools version of the Source Code:
https://lib.openmpt.org/files/libopenmpt/src/libopenmpt-0.4.12+release.autotools.tar.gz

2) Ran ./configure && make && make check && sudo make install against it. It took a few minutes and threw no apparent errors.

3) Attempted to build the "Hello World" code as shown here:
https://lib.openmpt.org/doc/libopenmpt_cpp_overview.html#libopenmpt_cpp_examples
...with the command clang++ libopenmpt-helloworld.cpp -std=c++11 -stdlib=libc++ -o libopenmpt-helloworld

4) I get back a lengthy error message but the first part is as follows:
Undefined symbols for architecture x86_64:
  "openmpt::module::read(int, unsigned long, float*, float*)", referenced from:
      _main in libopenmpt-helloworld-6960f1.o





Thanks for any help...I have a feeling I'm missing something very basic here! rs

manx

Quote from: ryansupak on May 06, 2020, 03:21:50
clang++ libopenmpt-helloworld.cpp -std=c++11 -stdlib=libc++ -o libopenmpt-helloworld

You are missing the linker libraries for both libopenmpt and portaudiocpp in the above command. The most portable way to obtain these is via pkg-config.

c++ libopenmpt_example_cxx.cpp -std=c++11 `pkg-config libopenmpt --cflags` `pkg-config portaudiocpp --cflags` `pkg-config libopenmpt --libs` `pkg-config portaudiocpp --libs` -o libopenmpt-example
works for me on Debian.

Note that portaudiocpp may be called differently on macOS (or may even not be packaged at all, in which case you can try building a C example instead of the C++ example, which requires only portaudio (and not portaudiocpp). The portaudio v19 pkg-config package is called portaudio-2.0 on Debian, but on macOS the name might be different. pkg-config --list-all might give a clue about the actual name (if you have portaudio installed).

[/quote]

ryansupak

#2
Thank you! Adding those additional parameters enabled a build. (There were some warnings but they were just "falling back to library file" items that didn't seem crucial.):

clang++ libopenmpt-helloworld.cpp -std=c++11 `pkg-config libopenmpt --cflags` `pkg-config portaudiocpp --cflags` `pkg-config libopenmpt --libs` `pkg-config portaudiocpp --libs` -o libopenmpt-helloworld

I did, however, encounter another problem. I tried invoking my newly-built command line program with a few different Tracker files in various formats, including the simplest-possible IT file with a single sample, that I made myself. No matter what file I choose, I get the following error -- here's an example:


$ ./libopenmpt-helloworld tempest-acidjazz.mod
Error: Sample format not supported


EDIT: The line causing it is as follows:


portaudio::BlockingStream stream( stream_parameters );


EDIT 2: I downloaded a PortAudio "hello world" for C++, that just plays a Sine Wave, and that builds and executes fine.

Thanks once again for any help or things to try! I still feel like I'm probably missing something basic...
rs

manx

Quote from: ryansupak on May 07, 2020, 00:37:52

$ ./libopenmpt-helloworld tempest-acidjazz.mod
Error: Sample format not supported


portaudio::BlockingStream stream( stream_parameters );

This is obviously a PortAudio problem, in particular probably of the macOS CoreAudio backend of PortAudio.

Maybe the attached patch fixes it (full source code also inline).


/*
* libopenmpt_example_cxx.cpp
* --------------------------
* Purpose: libopenmpt C++ API example
* Notes  : PortAudio C++ is used for sound output.
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/

/*
* Usage: libopenmpt_example_cxx SOMEMODULE
*/

#include <exception>
#include <fstream>
#include <iostream>
#include <new>
#include <stdexcept>
#include <vector>

#include <libopenmpt/libopenmpt.hpp>

#if defined(__clang__)
#if ((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 40000)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec"
#endif
#endif
#include <portaudiocpp/PortAudioCpp.hxx>
#if defined(__clang__)
#if ((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 40000)
#pragma clang diagnostic pop
#endif
#endif

#if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
#if defined( __GNUC__ )
// mingw-w64 g++ does only default to special C linkage for "main", but not for "wmain" (see <https://sourceforge.net/p/mingw-w64/wiki2/Unicode%20apps/>).
extern "C" int wmain( int argc, wchar_t * argv[] ) {
#else
int wmain( int argc, wchar_t * argv[] ) {
#endif
#else
int main( int argc, char * argv[] ) {
#endif
try {
if ( argc != 2 ) {
throw std::runtime_error( "Usage: libopenmpt_example_cxx SOMEMODULE" );
}
constexpr std::size_t buffersize = 480;
constexpr std::int32_t samplerate = 48000;
std::vector<float> buffer( buffersize * 2 );
std::ifstream file( argv[1], std::ios::binary );
openmpt::module mod( file );
portaudio::AutoSystem portaudio_initializer;
portaudio::System & portaudio = portaudio::System::instance();
portaudio::DirectionSpecificStreamParameters outputstream_parameters( portaudio.defaultOutputDevice(), 2, portaudio::FLOAT32, true, portaudio.defaultOutputDevice().defaultHighOutputLatency(), 0 );
portaudio::StreamParameters stream_parameters( portaudio::DirectionSpecificStreamParameters::null(), outputstream_parameters, samplerate, paFramesPerBufferUnspecified, paNoFlag );
portaudio::BlockingStream stream( stream_parameters );
stream.start();
while ( true ) {
std::size_t count = mod.read_interleaved_stereo( samplerate, buffersize, buffer.data() );
if ( count == 0 ) {
break;
}
try {
stream.write( buffer.data(), static_cast<unsigned long>( count ) );
} catch ( const portaudio::PaException & pa_exception ) {
if ( pa_exception.paError() != paOutputUnderflowed ) {
throw;
}
}
}
stream.stop();
} catch ( const std::bad_alloc & ) {
std::cerr << "Error: " << std::string( "out of memory" ) << std::endl;
return 1;
} catch ( const std::exception & e ) {
std::cerr << "Error: " << std::string( e.what() ? e.what() : "unknown error" ) << std::endl;
return 1;
}
return 0;
}



ryansupak

Thank you, manx! Switching the PortAudio code to "interleaved mode", as your code patch demonstrates, worked a treat for OSX.

ps - Sounds slightly better than playback in Schism Tracker does. ;)

Onward and upward :)
rs