Example #1
0
	static void initialize_tls()
	{
		// allocate if not initialized
		if (!g_tls_net_data)
		{
			g_tls_net_data.set(vm::alloc(sizeof(decltype(g_tls_net_data)::type), vm::main));

			thread_ctrl::at_exit([addr = g_tls_net_data.addr()]
			{
				vm::dealloc_verbose_nothrow(addr, vm::main);
			});
		}
	}
Example #2
0
	static never_inline void initialize_tls()
	{
		// allocate if not initialized
		if (!g_tls_net_data)
		{
			g_tls_net_data.set(vm::alloc(sizeof(decltype(g_tls_net_data)::type), vm::main));
			
			// Initial values
			g_tls_net_data->_errno = SYS_NET_EBUSY;

			thread_ctrl::atexit([addr = g_tls_net_data.addr()]
			{
				vm::dealloc_verbose_nothrow(addr, vm::main);
			});
		}
	}
Example #3
0
s32 cellSurMixerCreate(vm::cptr<CellSurMixerConfig> config)
{
	libmixer.Warning("cellSurMixerCreate(config=*0x%x)", config);

	g_surmx.audio_port = g_audio.open_port();

	if (!~g_surmx.audio_port)
	{
		return CELL_LIBMIXER_ERROR_FULL;
	}

	g_surmx.priority = config->priority;
	g_surmx.ch_strips_1 = config->chStrips1;
	g_surmx.ch_strips_2 = config->chStrips2;
	g_surmx.ch_strips_6 = config->chStrips6;
	g_surmx.ch_strips_8 = config->chStrips8;

	AudioPortConfig& port = g_audio.ports[g_surmx.audio_port];

	port.channel = 8;
	port.block = 16;
	port.attr = 0;
	port.addr = g_audio.buffer + AUDIO_PORT_OFFSET * g_surmx.audio_port;
	port.read_index_addr = g_audio.indexes + sizeof(u64) * g_surmx.audio_port;
	port.size = port.channel * port.block * AUDIO_SAMPLES * sizeof(float);
	port.tag = 0;
	port.level = 1.0f;
	port.level_set.data = { 1.0f, 0.0f };

	libmixer.Warning("*** audio port opened (port=%d)", g_surmx.audio_port);

	mixcount = 0;
	surMixerCb.set(0);

	libmixer.Warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)", config->chStrips1, config->chStrips2, config->chStrips6, config->chStrips8);

	auto ppu = Emu.GetIdManager().make_ptr<PPUThread>("Surmixer Thread");
	ppu->prio = 1001;
	ppu->stack_size = 0x10000;
	ppu->custom_task = [](PPUThread& CPU)
	{
		AudioPortConfig& port = g_audio.ports[g_surmx.audio_port];

		while (port.state.load() != AUDIO_PORT_STATE_CLOSED && !Emu.IsStopped())
		{
			if (mixcount > (port.tag + 0)) // adding positive value (1-15): preemptive buffer filling (hack)
			{
				std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
				continue;
			}

			if (port.state.load() == AUDIO_PORT_STATE_STARTED)
			{
				//u64 stamp0 = get_system_time();

				memset(mixdata, 0, sizeof(mixdata));
				if (surMixerCb)
				{
					surMixerCb(CPU, surMixerCbArg, (u32)mixcount, 256);
				}

				//u64 stamp1 = get_system_time();

				{
					std::lock_guard<std::mutex> lock(mixer_mutex);

					for (auto& p : ssp) if (p.m_active && p.m_created)
					{
						auto v = vm::ptrl<s16>::make(p.m_addr); // 16-bit LE audio data
						float left = 0.0f;
						float right = 0.0f;
						float speed = fabs(p.m_speed);
						float fpos = 0.0f;
						for (s32 i = 0; i < 256; i++) if (p.m_active)
						{
							u32 pos = p.m_position;
							s32 pos_inc = 0;
							if (p.m_speed > 0.0f) // select direction
							{
								pos_inc = 1;
							}
							else if (p.m_speed < 0.0f)
							{
								pos_inc = -1;
							}
							s32 shift = i - (int)fpos; // change playback speed (simple and rough)
							if (shift > 0)
							{
								// slow playback
								pos_inc = 0; // duplicate one sample at this time
								fpos += 1.0f;
								fpos += speed;
							}
							else if (shift < 0)
							{
								// fast playback
								i--; // mix two sample into one at this time
								fpos -= 1.0f;
							}
							else
							{
								fpos += speed;
							}
							p.m_position += (u32)pos_inc;
							if (p.m_channels == 1) // get mono data
							{
								left = right = (float)v[pos] / 0x8000 * p.m_level;
							}
							else if (p.m_channels == 2) // get stereo data
							{
								left = (float)v[pos * 2 + 0] / 0x8000 * p.m_level;
								right = (float)v[pos * 2 + 1] / 0x8000 * p.m_level;
							}
							if (p.m_connected) // mix
							{
								// TODO: m_x, m_y, m_z ignored
								mixdata[i * 8 + 0] += left;
								mixdata[i * 8 + 1] += right;
							}
							if ((p.m_position == p.m_samples && p.m_speed > 0.0f) ||
								(p.m_position == ~0 && p.m_speed < 0.0f)) // loop or stop
							{
								if (p.m_loop_mode == CELL_SSPLAYER_LOOP_ON)
								{
									p.m_position = p.m_loop_start;
								}
								else if (p.m_loop_mode == CELL_SSPLAYER_ONESHOT_CONT)
								{
									p.m_position -= (u32)pos_inc; // restore position
								}
								else // oneshot
								{
									p.m_active = false;
									p.m_position = p.m_loop_start; // TODO: check value
								}
							}
						}
					}
				}

				//u64 stamp2 = get_system_time();

				auto buf = vm::get_ptr<be_t<float>>(port.addr + (mixcount % port.block) * port.channel * AUDIO_SAMPLES * sizeof(float));

				for (u32 i = 0; i < (sizeof(mixdata) / sizeof(float)); i++)
				{
					// reverse byte order
					buf[i] = mixdata[i];
				}

				//u64 stamp3 = get_system_time();

				//ConLog.Write("Libmixer perf: start=%lld (cb=%lld, ssp=%lld, finalize=%lld)", stamp0 - m_config.start_time, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2);
			}

			mixcount++;
		}

		{
			std::lock_guard<std::mutex> lock(mixer_mutex);
			ssp.clear();
		}
		
		surMixerCb.set(0);

		const u32 id = CPU.GetId();

		CallAfter([id]()
		{
			Emu.GetIdManager().remove<PPUThread>(id);
		});
	};

	return CELL_OK;
}