Add project files.

This commit is contained in:
jobbywl 2024-06-21 08:22:20 +02:00
parent eec92af29e
commit f9e9d11825
17 changed files with 1010 additions and 0 deletions

51
AudioServer.sln Normal file
View file

@ -0,0 +1,51 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34031.279
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PulseAudio", "PulseAudio\PulseAudio.vcxproj", "{567419EA-59C6-4393-BBD3-D3850887AF8B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|ARM.ActiveCfg = Debug|ARM
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|ARM.Build.0 = Debug|ARM
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|ARM.Deploy.0 = Debug|ARM
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|ARM64.ActiveCfg = Debug|ARM64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|ARM64.Build.0 = Debug|ARM64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|ARM64.Deploy.0 = Debug|ARM64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|x64.ActiveCfg = Debug|x64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|x64.Build.0 = Debug|x64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|x64.Deploy.0 = Debug|x64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|x86.ActiveCfg = Debug|x86
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|x86.Build.0 = Debug|x86
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Debug|x86.Deploy.0 = Debug|x86
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|ARM.ActiveCfg = Release|ARM
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|ARM.Build.0 = Release|ARM
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|ARM.Deploy.0 = Release|ARM
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|ARM64.ActiveCfg = Release|ARM64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|ARM64.Build.0 = Release|ARM64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|ARM64.Deploy.0 = Release|ARM64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|x64.ActiveCfg = Release|x64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|x64.Build.0 = Release|x64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|x64.Deploy.0 = Release|x64
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|x86.ActiveCfg = Release|x86
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|x86.Build.0 = Release|x86
{567419EA-59C6-4393-BBD3-D3850887AF8B}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {1D344C9D-0E37-48CC-839F-E0B52A42FD1F}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,8 @@
#pragma once
class Subject;
class Observer
{
public:
virtual void update(Subject*) = 0;
};

View file

@ -0,0 +1,30 @@
#include "Subject.h"
#include "Observer.h"
Subject::Subject()
{
}
Subject::~Subject()
{
if (!mp_Observers.empty())
mp_Observers.clear();
}
void Subject::addObserver(Observer* obs)
{
mp_Observers.push_back(obs);
}
void Subject::delObserver(Observer* obs)
{
mp_Observers.remove(obs);
}
void Subject::notify(Subject* sub)
{
for (auto i : mp_Observers)
{
i->update(sub);
}
}

20
PulseAudio/3rd/Subject.h Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include <list>
class Observer;
class Subject
{
public:
Subject();
virtual ~Subject();
virtual void addObserver(Observer*);
virtual void delObserver(Observer*);
protected:
virtual void notify(Subject*);
private:
std::list<Observer*> mp_Observers;
};

78
PulseAudio/3rd/vban.cpp Normal file
View file

@ -0,0 +1,78 @@
#include "vban.h"
#include "PulseAudioCPP.h"
#include <tuple>
VBAN_Stream::VBAN_Stream(std::string name, VBAN_CODEC codec, VBAN_SAMPLERATE samplerate, VBAN_DATATYPE datatype, uint8_t noChannels)
:m_FrameCounter(0)
,m_name(name)
{
m_header.vban = VBAN_MARKER;
for (int i = 0; i < 16; i++)
m_header.streamname[i] = m_name.size() > i ? m_name[i] : 0;
m_header.format_bit = datatype & 0xf;
m_header.format_nbc = noChannels-1;
m_header.format_SR = samplerate;
m_header.format_nbs = 0;
m_header.noFrame = 0;
}
VBAN_Stream::~VBAN_Stream()
{
}
int VBAN_Stream::encodePacket(char* packet, uint16_t packetSize)
{
//std::cout << "Encode Packet " << packetSize << std::endl;
auto total = packetSize + sizeof(VBAN_HEADER);
auto newPacket = new char[total];
std::cout << (void*)newPacket << std::endl;
m_header.format_nbs = (packetSize / 8)-1;
m_header.noFrame = m_FrameCounter;
for (int i = 0; i < sizeof(m_header); i++)
newPacket[i] = ((char*)&m_header)[i];
for (int i = 0; i < packetSize; i++)
newPacket[i + sizeof(VBAN_HEADER)] = packet[i];
m_FrameCounter++;
m_packetBuffer.push_back({ newPacket,total });
//m_packetReadyCB(this, newPacket, packetSize);
return 0;
}
int VBAN_Stream::decodePacket(char* packet, uint16_t packetSize)
{
return 0;
}
std::pair<char*, unsigned int>* VBAN_Stream::getLastPacket()
{
if (m_packetBuffer.size() == 0)
return NULL;
return &m_packetBuffer.front();
}
void VBAN_Stream::dropLastPacket()
{
if (m_packetBuffer.size() > 0)
{
//auto pack = m_packetBuffer.front();
m_packetBuffer.pop_front();
//delete[] pack.first;
}
}
void VBAN_Stream::update(Subject* s)
{
PulseAudioCPP* pulseStream = (PulseAudioCPP*)s;
encodePacket(pulseStream->getBuffer(), pulseStream->getBufferSize());
}

174
PulseAudio/3rd/vban.h Normal file
View file

@ -0,0 +1,174 @@
#pragma once
#include <iostream>
#include "Observer.h"
#include "Subject.h"
#define MTU_SIZE 1500
#define VBAN_MAX_PACKET MTU_SIZE - sizeof(VBAN_HEADER) -28
typedef unsigned int uint32_t ;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
#define VBAN_MARKER 0x4e414256
#pragma pack(1)
struct VBAN_HEADER
{
uint32_t vban; // contains 'V' 'B', 'A', 'N'
uint8_t format_SR; // SR index (see SRList above)
uint8_t format_nbs; // nb sample per frame (1 to 256)
uint8_t format_nbc; // nb channel (1 to 256)
uint8_t format_bit; // mask = 0x07 (see DATATYPE table below)
char streamname[16]; // stream name
uint32_t noFrame; // growing frame number
};
#pragma pack()
#define VBAN_CODEC_PCM 0x00
#define VBAN_CODEC_VBCA 0x10 //VB-AUDIO AOIP CODEC
#define VBAN_CODEC_VBCV 0x20 //VB-AUDIO VOIP CODEC
#define VBAN_CODEC_UNDEFINED_1 0x30
#define VBAN_CODEC_UNDEFINED_2 0x40
#define VBAN_CODEC_UNDEFINED_3 0x50
#define VBAN_CODEC_UNDEFINED_4 0x60
#define VBAN_CODEC_UNDEFINED_5 0x70
#define VBAN_CODEC_UNDEFINED_6 0x80
#define VBAN_CODEC_UNDEFINED_7 0x90
#define VBAN_CODEC_UNDEFINED_8 0xA0
#define VBAN_CODEC_UNDEFINED_9 0xB0
#define VBAN_CODEC_UNDEFINED_10 0xC0
#define VBAN_CODEC_UNDEFINED_11 0xD0
#define VBAN_CODEC_UNDEFINED_12 0xE0
#define VBAN_CODEC_USER 0xF0
enum VBAN_CODEC
{
CODEC_PCM = 0x00,
CODEC_VBCA = 0x10,
CODEC_VBCV = 0x20,
CODEC_UNDEF1 = 0x30,
CODEC_UNDEF2 = 0x40,
CODEC_UNDEF3 = 0x50,
CODEC_UNDEF4 = 0x60,
CODEC_UNDEF5 = 0x70,
CODEC_UNDEF6 = 0x80,
CODEC_UNDEF7 = 0x90,
CODEC_UNDEF8 = 0xA0,
CODEC_UNDEF9 = 0xB0,
CODEC_UNDEF10 = 0xC0,
CODEC_UNDEF11 = 0xD0,
CODEC_UNDEF12 = 0xE0,
CODEC_USER = 0xF0
};
#define VBAN_DATATYPE_BYTE8 0x00
#define VBAN_DATATYPE_INT16 0x01
#define VBAN_DATATYPE_INT24 0x02
#define VBAN_DATATYPE_INT32 0x03
#define VBAN_DATATYPE_FLOAT32 0x04
#define VBAN_DATATYPE_FLOAT64 0x05
#define VBAN_DATATYPE_12BITS 0x06
#define VBAN_DATATYPE_10BITS 0x07
enum VBAN_DATATYPE
{
DATATYPE_BYTE8 = 0x00,
DATATYPE_INT16 = 0x01,
DATATYPE_INT24 = 0x02,
DATATYPE_INT32 = 0x03,
DATATYPE_FLOAT32= 0x04,
DATATYPE_FLOAT64= 0x05,
DATATYPE_12BITS =0x06,
DATATYPE_10BITS =0x07
};
#define VBAN_PROTOCOL_AUDIO 0x00
#define VBAN_PROTOCOL_SERIAL 0x20
#define VBAN_PROTOCOL_TXT 0x40
#define VBAN_PROTOCOL_SERVICE 0x60
#define VBAN_PROTOCOL_UNDEFINED_1 0x80
#define VBAN_PROTOCOL_UNDEFINED_2 0xA0
#define VBAN_PROTOCOL_UNDEFINED_3 0xC0
#define VBAN_PROTOCOL_USER 0xE0
enum VBAN_PROTOCOL
{
PROTOCOL_AUDIO = 0x00,
PROTOCOL_SERIAL = 0x20,
PROTOCOL_TXT = 0x40,
PROTOCOL_SERVICE = 0x60,
PROTOCOL_UNDEFINED_1 = 0x80,
PROTOCOL_UNDEFINED_2 = 0xA0,
PROTOCOL_UNDEFINED_3 = 0xC0,
PROTOCOL_USER = 0xE0
};
#define VBAN_SR_MAXNUMBER 21
static long VBAN_SRList[VBAN_SR_MAXNUMBER] =
{ 6000, 12000, 24000, 48000, 96000, 192000, 384000,
8000, 16000, 32000, 64000, 128000, 256000, 512000,
11025, 22050, 44100, 88200, 176400, 352800, 705600 };
enum VBAN_SAMPLERATE
{
SR_6000,
SR_12000,
SR_24000,
SR_48000,
SR_96000,
SR_192000,
SR_384000,
SR_8000,
SR_16000,
SR_32000,
SR_64000,
SR_128000,
SR_256000,
SR_512000,
SR_11025,
SR_22050,
SR_44100,
SR_88200,
SR_176400,
SR_352800,
SR_705600
};
class VBAN_Stream;
typedef int (*VBAN_StreamSamplesReady)(VBAN_Stream* stream, char* samples, int noSamples);
class VBAN_Stream :public Observer
{
public:
VBAN_Stream(std::string name, VBAN_CODEC codec, VBAN_SAMPLERATE samplerate, VBAN_DATATYPE datatype, uint8_t noChannels);
virtual ~VBAN_Stream();
int encodePacket(char * packet, uint16_t packetSize);
int decodePacket(char* packet, uint16_t packetSize);
std::pair<char*, unsigned int>* getLastPacket();
void dropLastPacket();
void update(Subject* s);
private:
std::string m_name;
VBAN_CODEC m_codec;
VBAN_SAMPLERATE m_samplerate;
VBAN_DATATYPE m_datatype;
uint8_t m_noChannels;
uint32_t m_FrameCounter;
VBAN_StreamSamplesReady m_packetReadyCB;
std::list<std::pair<char*,unsigned int>> m_packetBuffer;
VBAN_HEADER m_header;
};

View file

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x86">
<Configuration>Debug</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x86">
<Configuration>Release</Configuration>
<Platform>x86</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{567419ea-59c6-4393-bbd3-d3850887af8b}</ProjectGuid>
<Keyword>Linux</Keyword>
<RootNamespace>PulseAudio</RootNamespace>
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
<ApplicationType>Linux</ApplicationType>
<ApplicationTypeRevision>1.0</ApplicationTypeRevision>
<TargetLinuxPlatform>Generic</TargetLinuxPlatform>
<LinuxProjectType>{2238F9CD-F817-4ECC-BD14-2524D2669B35}</LinuxProjectType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="Shared" />
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>./inc;./ext</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>./inc;./3rd</IncludePath>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="3rd\vban.cpp" />
<ClCompile Include="src\PulseAudioStream.cpp" />
<ClCompile Include="src\PulseAudioCPP.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="3rd\Subject.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="3rd\vban.h" />
<ClInclude Include="inc\pulseaudioEnumPrint.h" />
<ClInclude Include="inc\PulseAudioCPP.h" />
<ClInclude Include="inc\PulseAudioStream.h" />
<ClInclude Include="3rd\Observer.h" />
<ClInclude Include="3rd\Subject.h" />
</ItemGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Link>
<LibraryDependencies>pulse</LibraryDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Link>
<LibraryDependencies>pulse</LibraryDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>

View file

@ -0,0 +1,43 @@
#pragma once
#include <string>
#include <pulse/pulseaudio.h>
#include <list>
#include "../3rd/Subject.h"
class PulseAudioCPP : public Subject
{
public:
PulseAudioCPP(std::string appName);
virtual ~PulseAudioCPP();
void createStream(std::string name);
char* getBuffer() { return mp_buffer; };
unsigned int getBufferSize() { return m_bytesInBuffer; };
private:
static void subscriptionCB(pa_context* c, pa_subscription_event_type_t t, uint32_t idx, void* userdata);
static void contextCB(pa_context* c, int success, void* userdata);
static void contextReadyCB(pa_context* context, void* userdata);
//stream callback
void readStream();
static void streamSuccessCB (pa_stream* s, int success, void* userdata);
static void streamRequestCB (pa_stream* p, size_t nbytes, void* userdata);
static void streamNotifyCB (pa_stream* p, void* userdata);
static void streamEventCB (pa_stream* p, const char* name, pa_proplist* pl, void* userdata);
private:
pa_threaded_mainloop* mp_threadedLoop;
pa_mainloop_api* mp_mainLoop;
pa_context* mp_context;
std::list<pa_stream*> mp_streamList;
char* mp_buffer;
unsigned int m_bytesInBuffer;
};

View file

@ -0,0 +1,19 @@
#pragma once
#include "PulseAudioCPP.h"
#include "../3rd/Subject.h"
class PulseAudioStream : public PulseAudioCPP
{
public:
PulseAudioStream(std::string name);
virtual ~PulseAudioStream();
int setSamplesReadyCallback();
private:
};

View file

@ -0,0 +1,53 @@
#pragma once
#include <ostream>
#include <pulse/subscribe.h>
std::ostream& operator<<(std::ostream& out, const pa_subscription_mask value) {
return out << [value] {
#define PROCESS_VAL(p) case(p): return #p;
switch (value) {
PROCESS_VAL(PA_SUBSCRIPTION_MASK_NULL);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_SINK);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_SOURCE);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_SINK_INPUT);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_MODULE);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_CLIENT);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_SAMPLE_CACHE);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_SERVER);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_AUTOLOAD);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_CARD);
PROCESS_VAL(PA_SUBSCRIPTION_MASK_ALL);
default:
return "Unkown Enum value";
}
#undef PROCESS_VAL
}();
}
std::ostream& operator<<(std::ostream& out, const pa_subscription_event_type value) {
return out << [value] {
#define PROCESS_VAL(p) case(p): return #p;
switch (value) {
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_SOURCE);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_SINK_INPUT);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_MODULE);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_CLIENT);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_SERVER);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_AUTOLOAD);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_CARD);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_FACILITY_MASK);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_CHANGE);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_REMOVE);
PROCESS_VAL(PA_SUBSCRIPTION_EVENT_TYPE_MASK);
case PA_SUBSCRIPTION_EVENT_NEW:
return "PA_SUBSCRIPTION_EVENT_NEW|PA_SUBSCRIPTION_EVENT_SINK";
default:
return "Unkown Enum value";
}
#undef PROCESS_VAL
}();
}

View file

@ -0,0 +1,152 @@
#include "PulseAudioCPP.h"
#include <iostream>
#include "pulseaudioEnumPrint.h"
#include <fstream>
PulseAudioCPP::PulseAudioCPP(std::string appName)
:mp_context(NULL)
, mp_mainLoop(NULL)
, mp_threadedLoop(NULL)
,mp_buffer(new char[4096])
{
mp_threadedLoop = pa_threaded_mainloop_new();
mp_mainLoop = pa_threaded_mainloop_get_api(mp_threadedLoop);
mp_context = pa_context_new(mp_mainLoop, "VBAN Audio Server");
pa_context_set_state_callback(mp_context, PulseAudioCPP::contextReadyCB, this);
pa_threaded_mainloop_lock(mp_threadedLoop);
pa_threaded_mainloop_start(mp_threadedLoop);
pa_context_connect(mp_context, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);
while (1)
{
pa_context_state_t context_state = pa_context_get_state(mp_context);
if (context_state == PA_CONTEXT_READY) break;
pa_threaded_mainloop_wait(mp_threadedLoop);
}
pa_context_subscribe(mp_context, PA_SUBSCRIPTION_MASK_ALL, PulseAudioCPP::contextCB, this);
pa_context_set_subscribe_callback(mp_context, PulseAudioCPP::subscriptionCB, this);
}
PulseAudioCPP::~PulseAudioCPP()
{
if (mp_context)
pa_context_disconnect(mp_context);
}
void PulseAudioCPP::createStream(std::string name)
{
pa_sample_spec spec;
spec.channels = 2;
spec.format = pa_sample_format_t::PA_SAMPLE_FLOAT32LE;
spec.rate = 44100;
pa_channel_map map;
map.channels = 2;
map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
pa_stream* newStream = pa_stream_new(mp_context, name.c_str(), &spec, &map);
pa_buffer_attr buff;
buff.fragsize = 1400; //VBAN Packet size
buff.maxlength = (uint32_t)-1;
buff.minreq = (uint32_t)-1;
buff.prebuf = (uint32_t)-1;
buff.tlength = (uint32_t)-1;
pa_stream_set_state_callback(newStream, PulseAudioCPP::streamNotifyCB, this);
pa_stream_set_read_callback(newStream, PulseAudioCPP::streamRequestCB, this);
pa_stream_connect_record(newStream, NULL, &buff, pa_stream_flags_t::PA_STREAM_NOFLAGS);
// Wait for the stream to be ready
for (;;) {
pa_stream_state_t stream_state = pa_stream_get_state(newStream);
if (stream_state == PA_STREAM_READY) break;
pa_threaded_mainloop_wait(mp_threadedLoop);
}
pa_threaded_mainloop_unlock(mp_threadedLoop);
mp_streamList.push_back(newStream);
}
void PulseAudioCPP::subscriptionCB(pa_context* c, pa_subscription_event_type_t t, uint32_t idx, void* instance)
{
auto ins = (PulseAudioCPP*)instance;
auto t1 = pa_subscription_event_type_t(t & 0x0f);
auto t2 = pa_subscription_event_type_t(t & 0xf0);
std::cout << "Subscription callback: " << idx << " " << t1 << " " << t2 << std::endl;
if (t2 == pa_subscription_event_type_t::PA_SUBSCRIPTION_EVENT_NEW && t1 == pa_subscription_event_type_t::PA_SUBSCRIPTION_EVENT_SINK_INPUT)
{
}
}
void PulseAudioCPP::contextCB(pa_context* c, int success, void* instance)
{
auto ins = (PulseAudioCPP*)instance;
std::cout << "Success: " << success << std::endl;
}
void PulseAudioCPP::contextReadyCB(pa_context* context, void* instance)
{
auto ins = (PulseAudioCPP*)instance;
std::cout << "Context state callback!" << std::endl;
pa_threaded_mainloop_signal((pa_threaded_mainloop*)ins->mp_threadedLoop, 0);
}
void PulseAudioCPP::readStream()
{
char* bufferp;
size_t size = 0;
auto s = mp_streamList.front();
if (s == NULL)
return;
pa_stream_peek(s, (const void**)&bufferp, &size);
m_bytesInBuffer = size;
for (int i = 0; i < size; i++)
mp_buffer[i] = bufferp[i];
//std::cout << "Samples: " << size / 8 << std::endl;
this->notify(this);
pa_stream_drop(s);
}
void PulseAudioCPP::streamSuccessCB(pa_stream* s, int success, void* userdata)
{
}
void PulseAudioCPP::streamRequestCB(pa_stream* p, size_t nbytes, void* userdata)
{
auto instance = (PulseAudioCPP*)userdata;
instance->readStream();
}
void PulseAudioCPP::streamNotifyCB(pa_stream* p, void* userdata)
{
auto ins = (PulseAudioCPP*)userdata;
std::cout << "Stream Notify callback!" << std::endl;
pa_threaded_mainloop_signal((pa_threaded_mainloop*)ins->mp_threadedLoop, 0);
}
void PulseAudioCPP::streamEventCB(pa_stream* p, const char* name, pa_proplist* pl, void* userdata)
{
}

View file

@ -0,0 +1 @@
#include "PulseAudioStream.h"

55
PulseAudio/src/main.cpp Normal file
View file

@ -0,0 +1,55 @@
#include <iostream>
#include <unistd.h>
#include "PulseAudioCPP.h"
#include "../3rd/vban.h"
#include <sys/socket.h>
#include <arpa/inet.h>
class udpStream
{
public:
udpStream(std::string target)
{
m_socket = socket(AF_INET, SOCK_DGRAM, 0);
for (int i = 0; i < sizeof(m_addr); i++)
((char*)&m_addr)[i] = 0;
m_addr.sin_family = AF_INET;
m_addr.sin_port = htons(6980);
inet_aton(target.c_str(), &m_addr.sin_addr);
}
virtual ~udpStream() {};
int send(const char* data, unsigned short size)
{
sendto(m_socket, data, size, 0, (struct sockaddr*)&m_addr, sizeof(m_addr));
}
private:
int m_socket;
struct sockaddr_in m_addr;
};
int main()
{
PulseAudioCPP vbanServer("vban server");
vbanServer.createStream("testStream");
VBAN_Stream stream("Stream1", VBAN_CODEC::CODEC_PCM, VBAN_SAMPLERATE::SR_44100, VBAN_DATATYPE::DATATYPE_FLOAT32, 2);
vbanServer.addObserver(&stream);
udpStream udp("192.168.10.19");
while (1)
{
auto packet = stream.getLastPacket();
if (packet != NULL)
{
udp.send(packet->first, packet->second);
stream.dropLastPacket();
}
}
return 0;
}

8
inc/vban-protocol.h Normal file
View file

@ -0,0 +1,8 @@
// vban-protocol.h : Include file for standard system include files,
// or project specific include files.
#pragma once
#include <iostream>
// TODO: Reference additional headers your program requires here.

179
inc/vban.h Normal file
View file

@ -0,0 +1,179 @@
#pragma once
#define WINDOWS 1
#ifdef WINDOWS
#include <iostream>
#endif // WINDOWS
#define MTU_SIZE 1500
#define VBAN_MAX_PACKET MTU_SIZE - sizeof(VBAN_HEADER) -28
typedef long long uint32_t ;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
#pragma pack(1)
struct VBAN_HEADER
{
uint32_t vban; // contains 'V' 'B', 'A', 'N'
uint8_t format_SR; // SR index (see SRList above)
uint8_t format_nbs; // nb sample per frame (1 to 256)
uint8_t format_nbc; // nb channel (1 to 256)
uint8_t format_bit; // mask = 0x07 (see DATATYPE table below)
char streamname[16]; // stream name
uint32_t nuFrame; // growing frame number
};
#pragma pack()
#define VBAN_CODEC_PCM 0x00
#define VBAN_CODEC_VBCA 0x10 //VB-AUDIO AOIP CODEC
#define VBAN_CODEC_VBCV 0x20 //VB-AUDIO VOIP CODEC
#define VBAN_CODEC_UNDEFINED_1 0x30
#define VBAN_CODEC_UNDEFINED_2 0x40
#define VBAN_CODEC_UNDEFINED_3 0x50
#define VBAN_CODEC_UNDEFINED_4 0x60
#define VBAN_CODEC_UNDEFINED_5 0x70
#define VBAN_CODEC_UNDEFINED_6 0x80
#define VBAN_CODEC_UNDEFINED_7 0x90
#define VBAN_CODEC_UNDEFINED_8 0xA0
#define VBAN_CODEC_UNDEFINED_9 0xB0
#define VBAN_CODEC_UNDEFINED_10 0xC0
#define VBAN_CODEC_UNDEFINED_11 0xD0
#define VBAN_CODEC_UNDEFINED_12 0xE0
#define VBAN_CODEC_USER 0xF0
enum VBAN_CODEC
{
CODEC_PCM = 0x00,
CODEC_VBCA = 0x10,
CODEC_VBCV = 0x20,
CODEC_UNDEF1 = 0x30,
CODEC_UNDEF2 = 0x40,
CODEC_UNDEF3 = 0x50,
CODEC_UNDEF4 = 0x60,
CODEC_UNDEF5 = 0x70,
CODEC_UNDEF6 = 0x80,
CODEC_UNDEF7 = 0x90,
CODEC_UNDEF8 = 0xA0,
CODEC_UNDEF9 = 0xB0,
CODEC_UNDEF10 = 0xC0,
CODEC_UNDEF11 = 0xD0,
CODEC_UNDEF12 = 0xE0,
CODEC_USER = 0xF0
};
#define VBAN_DATATYPE_BYTE8 0x00
#define VBAN_DATATYPE_INT16 0x01
#define VBAN_DATATYPE_INT24 0x02
#define VBAN_DATATYPE_INT32 0x03
#define VBAN_DATATYPE_FLOAT32 0x04
#define VBAN_DATATYPE_FLOAT64 0x05
#define VBAN_DATATYPE_12BITS 0x06
#define VBAN_DATATYPE_10BITS 0x07
enum VBAN_DATATYPE
{
DATATYPE_BYTE8 = 0x00,
DATATYPE_INT16 = 0x01,
DATATYPE_INT24 = 0x02,
DATATYPE_INT32 = 0x03,
DATATYPE_FLOAT32= 0x04,
DATATYPE_FLOAT64= 0x05,
DATATYPE_12BITS =0x06,
DATATYPE_10BITS =0x07
};
#define VBAN_PROTOCOL_AUDIO 0x00
#define VBAN_PROTOCOL_SERIAL 0x20
#define VBAN_PROTOCOL_TXT 0x40
#define VBAN_PROTOCOL_SERVICE 0x60
#define VBAN_PROTOCOL_UNDEFINED_1 0x80
#define VBAN_PROTOCOL_UNDEFINED_2 0xA0
#define VBAN_PROTOCOL_UNDEFINED_3 0xC0
#define VBAN_PROTOCOL_USER 0xE0
enum VBAN_PROTOCOL
{
PROTOCOL_AUDIO = 0x00,
PROTOCOL_SERIAL = 0x20,
PROTOCOL_TXT = 0x40,
PROTOCOL_SERVICE = 0x60,
PROTOCOL_UNDEFINED_1 = 0x80,
PROTOCOL_UNDEFINED_2 = 0xA0,
PROTOCOL_UNDEFINED_3 = 0xC0,
PROTOCOL_USER = 0xE0
};
#define VBAN_SR_MAXNUMBER 21
static long VBAN_SRList[VBAN_SR_MAXNUMBER] =
{ 6000, 12000, 24000, 48000, 96000, 192000, 384000,
8000, 16000, 32000, 64000, 128000, 256000, 512000,
11025, 22050, 44100, 88200, 176400, 352800, 705600 };
enum VBAN_SAMPLERATE
{
SR_6000,
SR_12000,
SR_24000,
SR_48000,
SR_96000,
SR_192000,
SR_384000,
SR_8000,
SR_16000,
SR_32000,
SR_64000,
SR_128000,
SR_256000,
SR_512000,
SR_11025,
SR_22050,
SR_44100,
SR_88200,
SR_176400,
SR_352800,
SR_705600
};
typedef int VBAN_StreamSamplesReady(VBAN_STREAM* stream, char* samples, int noSamples);
typedef struct VBAN_handle
{
VBAN_STREAM* streams;
uint8_t noStreams;
VBAN_StreamSamplesReady* readyCallback;
} VBAN_handle;
typedef struct VBAN_STREAM
{
char name[16];
VBAN_CODEC codec;
VBAN_SAMPLERATE samplerate;
VBAN_DATATYPE datatype;
uint8_t noChannels;
uint32_t frameCounter;
char* buffer;
uint16_t bufferSize;
} VBAN_STREAM;
//Returns -1 for error
int VBAN_Init(VBAN_handle*, char * buffer, uint16_t bufferSize);
int VBAN_GetCodec();
//Returns the size of the byte in the packet, -1 means error
int VBAN_Encode(VBAN_handle *handle, char *packet, uint16_t packetSize, char* audioStream, uint16_t noSamples);
//Returns the number of samples decoded from the packet, -1 means error
int VBAN_Decode(VBAN_handle* handle, char* packet, uint16_t packetSize, char* audioStream, uint16_t noSamples);

12
src/vban-protocol.cpp Normal file
View file

@ -0,0 +1,12 @@
// vban-protocol.cpp : Defines the entry point for the application.
//
#include "vban-protocol.h"
using namespace std;
int main()
{
cout << "Hello CMake." << endl;
return 0;
}

17
src/vban.c Normal file
View file

@ -0,0 +1,17 @@
#include "vban.h"
int VBAN_Init(VBAN_handle* h, char* buffer, uint16_t bufferSize)
{
return 0;
}
unsigned int VBAN_Encode(VBAN_handle* handle, char* packet, uint16_t packetSize, char* audioStream, uint16_t noSamples)
{
return 0;
}
unsigned int VBAN_Decode(VBAN_handle* handle, char* packet, uint16_t packetSize, char* audioStream, uint16_t noSamples)
{
return 0;
}